2011-02-10 85 views
2

我真的只是想有是关闭的,基于从here代码定制的TabItems一个TabControl。WPF定制的TabControl

我认为this question与我的相同,但代码& xaml的组合下面留下空的选项卡。

public class ClosableTabControl : TabControl 
{ 
    protected override DependencyObject GetContainerForItemOverride() 
    { 
     return new ClosableTabItem(); 
    } 
} 

     <uc:ClosableTabControl x:Name="Items" Grid.Column="1"> 
      <uc:ClosableTabControl.ItemTemplate> 
       <DataTemplate> 
        <TextBlock Text="{Binding DisplayName}" /> 
       </DataTemplate> 
      </uc:ClosableTabControl.ItemTemplate> 
      <uc:ClosableTabControl.ContentTemplate> 
       <DataTemplate> 
        <ContentControl> 
         <local:EmpView DataContext="{Binding ., Mode=TwoWay}"/> 
        </ContentControl> 
       </DataTemplate> 
      </uc:ClosableTabControl.ContentTemplate> 
     </uc:ClosableTabControl> 

xaml在TabControl(而不是uc:ClosableTabControl)上工作。

什么是有一个有孩子ClosableTabItems一个TabControl的最佳方式?

干杯,
Berryl

附:我会发布ClosableTabItem的代码,但我想在第一篇文章中将噪音水平降低。如果有帮助,请求我发布。

+0

你可以记住我的TabControl的例子,我用TabControl.ItemTemplate与被绑定到一个ViewModel命令关闭按钮。我的解决方案的优点是可以使用内部按钮关闭选项卡项目,例如保存或取消。 – vorrtex 2011-02-10 19:48:16

+0

这是一个silverlight例子,但无论如何,这里是链接:http:// stackoverflow。com/questions/4828661/silverlight-4-making-closeable-tabitems/4830314#4830314如果您已准备好使用ViewModels这样大量的数据,则可以将此示例重写为WPF。 – vorrtex 2011-02-10 19:54:07

回答

6

这里是我的TabControl的截图:

所有的

enter image description here

首先,关闭按钮是一个自定义控件,它允许使用不同颜色的悬停和按键状态。

Add -> New Item -> Custom Control -> GlyphButton 

GlyphButton.cs

public class GlyphButton : Button 
{ 
    public static readonly DependencyProperty GlyphForegroundProperty = DependencyProperty.Register("GlyphForeground", typeof(Brush), typeof(GlyphButton)); 
    public static readonly DependencyProperty HoverBackgroundProperty = DependencyProperty.Register("HoverBackground", typeof(Brush), typeof(GlyphButton)); 
    public static readonly DependencyProperty HoverBorderBrushProperty = DependencyProperty.Register("HoverBorderBrush", typeof(Brush), typeof(GlyphButton)); 
    public static readonly DependencyProperty HoverBorderThicknessProperty = DependencyProperty.Register("HoverBorderThickness", typeof(Thickness), typeof(GlyphButton)); 
    public static readonly DependencyProperty HoverForegroundProperty = DependencyProperty.Register("HoverForeground", typeof(Brush), typeof(GlyphButton)); 
    public static readonly DependencyProperty PressedBackgroundProperty = DependencyProperty.Register("PressedBackground", typeof(Brush), typeof(GlyphButton)); 
    public static readonly DependencyProperty PressedBorderBrushProperty = DependencyProperty.Register("PressedBorderBrush", typeof(Brush), typeof(GlyphButton)); 
    public static readonly DependencyProperty PressedBorderThicknessProperty = DependencyProperty.Register("PressedBorderThickness", typeof(Thickness), typeof(GlyphButton)); 
    public static readonly DependencyProperty PressedForegroundProperty = DependencyProperty.Register("PressedForeground", typeof(Brush), typeof(GlyphButton)); 

    static GlyphButton() 
    { 
     DefaultStyleKeyProperty.OverrideMetadata(typeof(GlyphButton), new FrameworkPropertyMetadata(typeof(GlyphButton))); 
    } 

    public Brush GlyphForeground 
    { 
     get 
     { 
      return (Brush)base.GetValue(GlyphForegroundProperty); 
     } 
     set 
     { 
      base.SetValue(GlyphForegroundProperty, value); 
     } 
    } 

    public Brush HoverBackground 
    { 
     get 
     { 
      return (Brush)base.GetValue(HoverBackgroundProperty); 
     } 
     set 
     { 
      base.SetValue(HoverBackgroundProperty, value); 
     } 
    } 

    public Brush HoverBorderBrush 
    { 
     get 
     { 
      return (Brush)base.GetValue(HoverBorderBrushProperty); 
     } 
     set 
     { 
      base.SetValue(HoverBorderBrushProperty, value); 
     } 
    } 

    public Thickness HoverBorderThickness 
    { 
     get 
     { 
      return (Thickness)base.GetValue(HoverBorderThicknessProperty); 
     } 
     set 
     { 
      base.SetValue(HoverBorderThicknessProperty, value); 
     } 
    } 

    public Brush HoverForeground 
    { 
     get 
     { 
      return (Brush)base.GetValue(HoverForegroundProperty); 
     } 
     set 
     { 
      base.SetValue(HoverForegroundProperty, value); 
     } 
    } 

    public Brush PressedBackground 
    { 
     get 
     { 
      return (Brush)base.GetValue(PressedBackgroundProperty); 
     } 
     set 
     { 
      base.SetValue(PressedBackgroundProperty, value); 
     } 
    } 

    public Brush PressedBorderBrush 
    { 
     get 
     { 
      return (Brush)base.GetValue(PressedBorderBrushProperty); 
     } 
     set 
     { 
      base.SetValue(PressedBorderBrushProperty, value); 
     } 
    } 

    public Thickness PressedBorderThickness 
    { 
     get 
     { 
      return (Thickness)base.GetValue(PressedBorderThicknessProperty); 
     } 
     set 
     { 
      base.SetValue(PressedBorderThicknessProperty, value); 
     } 
    } 

    public Brush PressedForeground 
    { 
     get 
     { 
      return (Brush)base.GetValue(PressedForegroundProperty); 
     } 
     set 
     { 
      base.SetValue(PressedForegroundProperty, value); 
     } 
    } 
} 

主题/ Generic.xaml

<Style TargetType="{x:Type local:GlyphButton}"> 
    <Setter Property="Width" Value="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}" /> 
    <Setter Property="Foreground" Value="{Binding Path=GlyphForeground, RelativeSource={RelativeSource Self}}" /> 
    <Setter Property="Background" Value="Transparent" /> 
    <Setter Property="BorderBrush" Value="Transparent" /> 
    <Setter Property="BorderThickness" Value="1" /> 
    <Setter Property="Focusable" Value="false" /> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type local:GlyphButton}"> 
       <Border Name="Border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> 
        <ContentPresenter /> 
       </Border> 
       <ControlTemplate.Triggers> 
        <Trigger Property="IsMouseOver" Value="true"> 
         <Setter TargetName="Border" Value="{Binding HoverBackground , RelativeSource={RelativeSource TemplatedParent}}" Property="Background" /> 
         <Setter TargetName="Border" Value="{Binding HoverBorderBrush , RelativeSource={RelativeSource TemplatedParent}}" Property="BorderBrush" /> 
         <Setter TargetName="Border" Value="{Binding HoverBorderThickness , RelativeSource={RelativeSource TemplatedParent}}" Property="BorderThickness" /> 
         <Setter Value="{Binding HoverForeground , RelativeSource={RelativeSource TemplatedParent}}" Property="Foreground" /> 
        </Trigger> 
        <Trigger Property="IsPressed" Value="True"> 
         <Setter TargetName="Border" Value="{Binding PressedBackground , RelativeSource={RelativeSource TemplatedParent}}" Property="Background" /> 
         <Setter TargetName="Border" Value="{Binding PressedBorderBrush , RelativeSource={RelativeSource TemplatedParent}}" Property="BorderBrush" /> 
         <Setter TargetName="Border" Value="{Binding PressedBorderThickness , RelativeSource={RelativeSource TemplatedParent}}" Property="BorderThickness" /> 
         <Setter Value="{Binding PressedForeground , RelativeSource={RelativeSource TemplatedParent}}" Property="Foreground" /> 
        </Trigger> 
       </ControlTemplate.Triggers> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

样式用于TabItem。你可以把它放在任何地方,在App.xaml或资源字典中。

TabItem的风格

<SolidColorBrush x:Key="FileTabTextKey" Color="#ffffff"/> 

<SolidColorBrush x:Key="ToolWindowButtonHoverActiveKey" Color="#fffcf4"/> 
<SolidColorBrush x:Key="ToolWindowButtonHoverActiveBorderKey" Color="#e5c365"/> 
<SolidColorBrush x:Key="ToolWindowButtonHoverActiveGlyphKey" Color="#000000"/> 
<SolidColorBrush x:Key="ToolWindowButtonDownKey" Color="#ffe8a6"/> 
<SolidColorBrush x:Key="ToolWindowButtonDownBorderKey" Color="#e5c365"/> 
<SolidColorBrush x:Key="ToolWindowButtonDownActiveGlyphKey" Color="#000000"/> 

<LinearGradientBrush x:Key="FileTabHotGradientKey"> 
    <GradientStop Color="#707776"/> 
    <GradientStop Color="#4b5c74"/> 
</LinearGradientBrush> 
<SolidColorBrush x:Key="FileTabHotBorderKey" Color="#9ba7b7"/> 
<SolidColorBrush x:Key="FileTabHotTextKey" Color="#ffffff"/> 
<SolidColorBrush x:Key="FileTabHotGlyphKey" Color="#ced4dd"/> 

<LinearGradientBrush x:Key="FileTabSelectedGradientKey" StartPoint="0.5,0" EndPoint="0.5,1"> 
    <GradientStop Color="#fffcf4"/> 
    <GradientStop Color="#fff3cd" Offset="0.5"/> 
    <GradientStop Color="#ffe8a6" Offset="0.5"/> 
    <GradientStop Color="#ffe8a6" Offset="1"/> 
</LinearGradientBrush> 
<SolidColorBrush x:Key="FileTabSelectedTextKey" Color="#000000"/> 
<SolidColorBrush x:Key="FileTabSelectedGlyphKey" Color="#75633d"/> 

<Style x:Key="OrangeTabItem" TargetType="{x:Type TabItem}"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type TabItem}"> 
       <Border AllowDrop="true" ToolTip="{Binding Title}"> 
        <Border Name="Border" Background="Transparent" BorderBrush="Transparent" BorderThickness="1,1,1,0" CornerRadius="2,2,0,0"> 
         <DockPanel x:Name="TitlePanel" TextElement.Foreground="{StaticResource FileTabTextKey}"> 
          <controls:GlyphButton x:Name="HideButton" 
          DockPanel.Dock="Right" 
          GlyphForeground="Transparent" 
          HoverBackground="{StaticResource ToolWindowButtonHoverActiveKey}" 
          HoverBorderBrush="{StaticResource ToolWindowButtonHoverActiveBorderKey}" 
          HoverForeground="{StaticResource ToolWindowButtonHoverActiveGlyphKey}" 
          PressedBackground="{StaticResource ToolWindowButtonDownKey}" 
          PressedBorderBrush="{StaticResource ToolWindowButtonDownBorderKey}" 
          PressedForeground="{StaticResource ToolWindowButtonDownActiveGlyphKey}" 
          HoverBorderThickness="1" PressedBorderThickness="1" Margin="3,2,3,4" 
          Command="{Binding RequestCloseCommand}" 
          CommandParameter="{Binding}" 
          ToolTip="Close"> 
           <Path x:Name="CloseButtonStroke" Width="10" Height="8" Stretch="Uniform" Data="F1 M 0,0 L 2,0 5,3 8,0 10,0 6,4 10,8 8,8 5,5 2,8 0,8 4,4 0,0 Z" 
           Fill="{Binding Path=(TextElement.Foreground), RelativeSource={RelativeSource Self}}" /> 
          </controls:GlyphButton> 

          <ContentPresenter x:Name="Content" HorizontalAlignment="Stretch" Margin="4,2,4,4" VerticalAlignment="Stretch" RecognizesAccessKey="true" ContentSource="Header" /> 
         </DockPanel> 
        </Border> 
       </Border> 
       <ControlTemplate.Triggers> 
        <Trigger Property="IsMouseOver" Value="true"> 
         <Setter TargetName="Border" Value="{StaticResource FileTabHotGradientKey}" Property="Background" /> 
         <Setter TargetName="Border" Value="{StaticResource FileTabHotBorderKey}" Property="BorderBrush" /> 
         <Setter TargetName="TitlePanel" Value="{StaticResource FileTabHotTextKey}" Property="TextElement.Foreground" /> 
         <Setter TargetName="HideButton" Value="{StaticResource FileTabHotGlyphKey}" Property="GlyphForeground" /> 
        </Trigger> 
        <Trigger Property="IsSelected" Value="True"> 
         <Setter Property="Panel.ZIndex" Value="1" /> 
         <Setter TargetName="Border" Value="{StaticResource FileTabSelectedGradientKey}" Property="Background" /> 
         <Setter TargetName="Border" Value="{StaticResource FileTabSelectedGradientKey}" Property="BorderBrush" /> 
         <Setter TargetName="Border" Property="BorderThickness" Value="0" /> 
         <Setter TargetName="Border" Property="Padding" Value="0,1,0,0" /> 
         <Setter TargetName="HideButton" Property="Margin" Value="3" /> 
         <Setter TargetName="TitlePanel" Value="{StaticResource FileTabSelectedTextKey}" Property="TextElement.Foreground" /> 
         <Setter TargetName="HideButton" Value="{StaticResource FileTabSelectedGlyphKey}" Property="GlyphForeground" /> 
        </Trigger> 
       </ControlTemplate.Triggers> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

现在Main Window。我的TabControl需要蓝色背景,但您可以根据需要更改颜色。

<Grid Background="#FF293955"> 
    <TabControl ItemsSource="{Binding Items}" ItemContainerStyle="{StaticResource OrangeTabItem}"> 
     <TabControl.ItemTemplate> 
      <DataTemplate> 
       <TextBlock Text="{Binding Title}"/> 
      </DataTemplate> 
     </TabControl.ItemTemplate> 
     <TabControl.ContentTemplate> 
      <DataTemplate> 
       <ContentControl Content="{Binding Content}"/> 
      </DataTemplate> 
     </TabControl.ContentTemplate> 
    </TabControl> 
</Grid> 

最后一个重要的一句话:代表TabItem必须包含命令两个ViewModels

public class MainViewModel 
{ 
    public MainViewModel() 
    { 
     this.Items = new ObservableCollection<TabItemViewModel> 
        { 
         new TabItemViewModel("Tab 1", OnItemRequestClose), 
         new TabItemViewModel("Tab item 2", OnItemRequestClose) 
        }; 
    } 

    public ObservableCollection<TabItemViewModel> Items { get; set; } 

    public void OnItemRequestClose(TabItemViewModel item) 
    { 
     this.Items.Remove(item); 
    } 
} 

public class TabItemViewModel 
{ 
    public TabItemViewModel(string title, Action<TabItemViewModel> onClose) 
    { 
     this.Title = title; 
     this.RequestCloseCommand = new SimpleCommand(obj => onClose(this)); 
     this.Content = "Test content " + title; 
    } 

    public string Title { get; set; } 

    public ICommand RequestCloseCommand { get; set; } 

    public object Content { get; set; } 
} 

RequestCloseCommand

例子我想过使用RoutedUICommand但它会花很多时间到模型修改这种类型的命令。所以这个解决方案对我来说是最合适的。