WPF如何自定義TabControl控件樣式示例詳解
一、前言
程序中經(jīng)常會(huì)用到TabControl控件,默認(rèn)的控件樣式很普通。而且樣式或功能不一定符合我們的要求。比如:我們需要TabControl的標(biāo)題能夠居中、或平均分布;或者我們希望TabControl的標(biāo)題能夠進(jìn)行關(guān)閉。要實(shí)現(xiàn)這些功能我們需要對(duì)TabControl的樣式進(jìn)行定義。
二、實(shí)現(xiàn)TabControl的標(biāo)題平均分布
默認(rèn)的TabControl標(biāo)題是使用TabPanel容器包含的。要想實(shí)現(xiàn)TabControl標(biāo)題頭平均分布,需要把TabPanel替換成UniformGrid;
替換后的TabControl樣式如下:
<Style x:Key="TabControlStyle" TargetType="{x:Type TabControl}"> <Setter Property="Padding" Value="2"/> <Setter Property="HorizontalContentAlignment" Value="Center"/> <Setter Property="VerticalContentAlignment" Value="Center"/> <Setter Property="Background" Value="White"/> <Setter Property="BorderBrush" Value="#FFACACAC"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type TabControl}"> <Grid x:Name="templateRoot" ClipToBounds="True" SnapsToDevicePixels="True" KeyboardNavigation.TabNavigation="Local"> <Grid.ColumnDefinitions> <ColumnDefinition x:Name="ColumnDefinition0"/> <ColumnDefinition x:Name="ColumnDefinition1" Width="0"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition x:Name="RowDefinition0" Height="Auto"/> <RowDefinition x:Name="RowDefinition1" Height="*"/> </Grid.RowDefinitions> <UniformGrid x:Name="HeaderPanel" Rows="1" Background="Transparent" Grid.Column="0" IsItemsHost="True" Margin="0" Grid.Row="0" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1"/> <Line X1="0" X2="{Binding ActualWidth, RelativeSource={RelativeSource Self}}" Stroke="White" StrokeThickness="0.1" VerticalAlignment="Bottom" Margin="0 0 0 1" SnapsToDevicePixels="True"/> <Border x:Name="ContentPanel" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="0" KeyboardNavigation.DirectionalNavigation="Contained" Grid.Row="1" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local"> <ContentPresenter x:Name="PART_SelectedContentHost" ContentTemplate="{TemplateBinding SelectedContentTemplate}" Content="{TemplateBinding SelectedContent}" ContentStringFormat="{TemplateBinding SelectedContentStringFormat}" ContentSource="SelectedContent" Margin="0" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> </Border> </Grid> <ControlTemplate.Triggers> <Trigger Property="TabStripPlacement" Value="Bottom"> <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="1"/> <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/> <Setter Property="Height" TargetName="RowDefinition0" Value="*"/> <Setter Property="Height" TargetName="RowDefinition1" Value="Auto"/> </Trigger> <Trigger Property="TabStripPlacement" Value="Left"> <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/> <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/> <Setter Property="Grid.Column" TargetName="HeaderPanel" Value="0"/> <Setter Property="Grid.Column" TargetName="ContentPanel" Value="1"/> <Setter Property="Width" TargetName="ColumnDefinition0" Value="Auto"/> <Setter Property="Width" TargetName="ColumnDefinition1" Value="*"/> <Setter Property="Height" TargetName="RowDefinition0" Value="*"/> <Setter Property="Height" TargetName="RowDefinition1" Value="0"/> </Trigger> <Trigger Property="TabStripPlacement" Value="Right"> <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/> <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/> <Setter Property="Grid.Column" TargetName="HeaderPanel" Value="1"/> <Setter Property="Grid.Column" TargetName="ContentPanel" Value="0"/> <Setter Property="Width" TargetName="ColumnDefinition0" Value="*"/> <Setter Property="Width" TargetName="ColumnDefinition1" Value="Auto"/> <Setter Property="Height" TargetName="RowDefinition0" Value="*"/> <Setter Property="Height" TargetName="RowDefinition1" Value="0"/> </Trigger> <Trigger Property="IsEnabled" Value="False"> <Setter Property="TextElement.Foreground" TargetName="templateRoot" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
即使這樣設(shè)置了,TabControl的標(biāo)題還是很丑,這個(gè)時(shí)候就需要通過(guò)設(shè)置TabItem來(lái)更改標(biāo)題樣式了。
TabItem樣式如下:
<Style x:Key="TabItemStyle" TargetType="{x:Type TabItem}"> <Setter Property="Foreground" Value="White"/> <Setter Property="Background" Value="Transparent"/> <Setter Property="BorderBrush" Value="#FFACACAC"/> <Setter Property="Margin" Value="0"/> <Setter Property="HorizontalContentAlignment" Value="Stretch"/> <Setter Property="VerticalContentAlignment" Value="Stretch"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type TabItem}"> <Grid x:Name="templateRoot" SnapsToDevicePixels="True" Background="Transparent"> <TextBlock x:Name="txt" Visibility="Visible" VerticalAlignment="Center" HorizontalAlignment="Center" Text="{TemplateBinding Header}" ToolTip="{TemplateBinding Header}" Foreground="{TemplateBinding Foreground}" TextTrimming="CharacterEllipsis" /> </Grid> <ControlTemplate.Triggers> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}" Value="true"/> <Condition Binding="{Binding TabStripPlacement, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type TabControl}}}" Value="Top"/> </MultiDataTrigger.Conditions> <Setter Property="Foreground" TargetName="txt" Value="#fffea1"/> </MultiDataTrigger> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource Self}}" Value="false"/> <Condition Binding="{Binding TabStripPlacement, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type TabControl}}}" Value="Left"/> </MultiDataTrigger.Conditions> <Setter Property="Opacity" TargetName="templateRoot" Value="0.56"/> </MultiDataTrigger> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource Self}}" Value="false"/> <Condition Binding="{Binding TabStripPlacement, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type TabControl}}}" Value="Bottom"/> </MultiDataTrigger.Conditions> <Setter Property="Opacity" TargetName="templateRoot" Value="0.56"/> </MultiDataTrigger> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource Self}}" Value="false"/> <Condition Binding="{Binding TabStripPlacement, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type TabControl}}}" Value="Right"/> </MultiDataTrigger.Conditions> <Setter Property="Opacity" TargetName="templateRoot" Value="0.56"/> </MultiDataTrigger> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource Self}}" Value="false"/> <Condition Binding="{Binding TabStripPlacement, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type TabControl}}}" Value="Top"/> </MultiDataTrigger.Conditions> <Setter Property="Opacity" TargetName="templateRoot" Value="0.56"/> </MultiDataTrigger> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding IsSelected, RelativeSource={RelativeSource Self}}" Value="true"/> <Condition Binding="{Binding TabStripPlacement, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type TabControl}}}" Value="Top"/> </MultiDataTrigger.Conditions> <Setter Property="Panel.ZIndex" Value="1"/> <Setter Property="Foreground" TargetName="txt" Value="#fffea1"/> </MultiDataTrigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
至此,樣式已經(jīng)設(shè)置完畢,引用示例:
<Grid Background="#858586"> <TabControl Style="{StaticResource TabControlStyle}" Width="300" Height="200" Background="Transparent" BorderBrush="Transparent" BorderThickness="0"> <TabItem Style="{StaticResource TabItemStyle}" Cursor="Hand" Header="音樂(lè)電臺(tái)" Height="38" > <Grid Background="#33ffffff"> <TextBlock Text="音樂(lè)電臺(tái)" VerticalAlignment="Center" HorizontalAlignment="Center"/> </Grid> </TabItem> <TabItem Style="{StaticResource TabItemStyle}" Cursor="Hand" Header="Mv電臺(tái)" Height="38" > <Grid Background="#33ffffff"> <TextBlock Text="Mv電臺(tái)" VerticalAlignment="Center" HorizontalAlignment="Center"/> </Grid> </TabItem> </TabControl> </Grid>
效果如下:
三、實(shí)現(xiàn)TabControl標(biāo)題居中顯示(不平均分布)
同理需要更改TabControl的樣式和TabItem的樣式。需要把使用TabPanel作為標(biāo)題的容器,設(shè)置HorizontalAlignment為Center;
TabControl的樣式如下:
<Style x:Key="TabControlWithUnderLineStyle" TargetType="{x:Type TabControl}"> <Setter Property="Padding" Value="2"/> <Setter Property="HorizontalContentAlignment" Value="Center"/> <Setter Property="VerticalContentAlignment" Value="Center"/> <Setter Property="Background" Value="White"/> <Setter Property="BorderBrush" Value="#FFACACAC"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type TabControl}"> <Grid x:Name="templateRoot" ClipToBounds="True" SnapsToDevicePixels="True" KeyboardNavigation.TabNavigation="Local"> <Grid.ColumnDefinitions> <ColumnDefinition x:Name="ColumnDefinition0"/> <ColumnDefinition x:Name="ColumnDefinition1" Width="0"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition x:Name="RowDefinition0" Height="Auto"/> <RowDefinition x:Name="RowDefinition1" Height="*"/> </Grid.RowDefinitions> <TabPanel x:Name="HeaderPanel" HorizontalAlignment="Center" Background="Transparent" Grid.Column="0" IsItemsHost="True" Margin="0" Grid.Row="0" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1"/> <Line X1="0" X2="{Binding ActualWidth, RelativeSource={RelativeSource Self}}" Stroke="Gray" StrokeThickness="0.1" VerticalAlignment="Bottom" Margin="0 0 0 1" SnapsToDevicePixels="True"/> <Border x:Name="ContentPanel" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="0" KeyboardNavigation.DirectionalNavigation="Contained" Grid.Row="1" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local"> <ContentPresenter x:Name="PART_SelectedContentHost" ContentTemplate="{TemplateBinding SelectedContentTemplate}" Content="{TemplateBinding SelectedContent}" ContentStringFormat="{TemplateBinding SelectedContentStringFormat}" ContentSource="SelectedContent" Margin="0" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> </Border> </Grid> <ControlTemplate.Triggers> <Trigger Property="TabStripPlacement" Value="Bottom"> <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="1"/> <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/> <Setter Property="Height" TargetName="RowDefinition0" Value="*"/> <Setter Property="Height" TargetName="RowDefinition1" Value="Auto"/> </Trigger> <Trigger Property="TabStripPlacement" Value="Left"> <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/> <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/> <Setter Property="Grid.Column" TargetName="HeaderPanel" Value="0"/> <Setter Property="Grid.Column" TargetName="ContentPanel" Value="1"/> <Setter Property="Width" TargetName="ColumnDefinition0" Value="Auto"/> <Setter Property="Width" TargetName="ColumnDefinition1" Value="*"/> <Setter Property="Height" TargetName="RowDefinition0" Value="*"/> <Setter Property="Height" TargetName="RowDefinition1" Value="0"/> </Trigger> <Trigger Property="TabStripPlacement" Value="Right"> <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/> <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/> <Setter Property="Grid.Column" TargetName="HeaderPanel" Value="1"/> <Setter Property="Grid.Column" TargetName="ContentPanel" Value="0"/> <Setter Property="Width" TargetName="ColumnDefinition0" Value="*"/> <Setter Property="Width" TargetName="ColumnDefinition1" Value="Auto"/> <Setter Property="Height" TargetName="RowDefinition0" Value="*"/> <Setter Property="Height" TargetName="RowDefinition1" Value="0"/> </Trigger> <Trigger Property="IsEnabled" Value="False"> <Setter Property="TextElement.Foreground" TargetName="templateRoot" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
TabItem樣式如下:
<Style x:Key="TabItemExWithUnderLineStyle" TargetType="{x:Type TabItem}"> <Setter Property="Foreground" Value="White"/> <Setter Property="Background" Value="Transparent"/> <Setter Property="BorderBrush" Value="#FFACACAC"/> <Setter Property="Margin" Value="0"/> <Setter Property="HorizontalContentAlignment" Value="Stretch"/> <Setter Property="VerticalContentAlignment" Value="Stretch"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type TabItem}"> <Grid x:Name="templateRoot" SnapsToDevicePixels="True" Background="Transparent"> <Border x:Name="_underline" BorderBrush="#37aefe" BorderThickness="0" Margin="{TemplateBinding Margin}"/> <Grid> <TextBlock x:Name="txt" Visibility="Visible" VerticalAlignment="Center" HorizontalAlignment="Center" Text="{TemplateBinding Header}" ToolTip="{TemplateBinding Header}" Foreground="{TemplateBinding Foreground}" TextTrimming="CharacterEllipsis" /> </Grid> </Grid> <ControlTemplate.Triggers> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}" Value="true"/> <Condition Binding="{Binding TabStripPlacement, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type TabControl}}}" Value="Top"/> </MultiDataTrigger.Conditions> <Setter Property="Foreground" TargetName="txt" Value="#37aefe"/> </MultiDataTrigger> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource Self}}" Value="false"/> <Condition Binding="{Binding TabStripPlacement, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type TabControl}}}" Value="Left"/> </MultiDataTrigger.Conditions> <Setter Property="Opacity" TargetName="templateRoot" Value="0.56"/> </MultiDataTrigger> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource Self}}" Value="false"/> <Condition Binding="{Binding TabStripPlacement, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type TabControl}}}" Value="Bottom"/> </MultiDataTrigger.Conditions> <Setter Property="Opacity" TargetName="templateRoot" Value="0.56"/> </MultiDataTrigger> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource Self}}" Value="false"/> <Condition Binding="{Binding TabStripPlacement, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type TabControl}}}" Value="Right"/> </MultiDataTrigger.Conditions> <Setter Property="Opacity" TargetName="templateRoot" Value="0.56"/> </MultiDataTrigger> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource Self}}" Value="false"/> <Condition Binding="{Binding TabStripPlacement, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type TabControl}}}" Value="Top"/> </MultiDataTrigger.Conditions> <Setter Property="Opacity" TargetName="templateRoot" Value="0.56"/> </MultiDataTrigger> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding IsSelected, RelativeSource={RelativeSource Self}}" Value="true"/> <Condition Binding="{Binding TabStripPlacement, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type TabControl}}}" Value="Top"/> </MultiDataTrigger.Conditions> <Setter Property="Panel.ZIndex" Value="1"/> <Setter Property="Foreground" TargetName="txt" Value="#37aefe"/> <Setter Property="BorderThickness" TargetName="_underline" Value="0 0 0 2"/> </MultiDataTrigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
引用示例:
<Grid Background="#858586"> <TabControl Style="{StaticResource TabControlWithUnderLineStyle}" Foreground="Black" Width="300" Height="200" Background="Transparent" BorderBrush="Transparent" BorderThickness="0"> <TabItem Style="{StaticResource TabItemExWithUnderLineStyle}" Cursor="Hand" Header="音樂(lè)電臺(tái)" Height="38" Width="70" Margin="5 0"> <Grid Background="#33ffffff"> <TextBlock Text="音樂(lè)電臺(tái)" VerticalAlignment="Center" HorizontalAlignment="Center"/> </Grid> </TabItem> <TabItem Style="{StaticResource TabItemExWithUnderLineStyle}" Cursor="Hand" Header="Mv電臺(tái)" Height="38" Width="70" Margin="5 0"> <Grid Background="#33ffffff"> <TextBlock Text="Mv電臺(tái)" VerticalAlignment="Center" HorizontalAlignment="Center"/> </Grid> </TabItem> </TabControl> </Grid>
效果如下:
四、帶關(guān)閉按鈕的TabControl
帶關(guān)閉按鈕的TabControl其實(shí)就是就是擴(kuò)展TabItem,需要新建WPF自定義控件,命名為TabItemClose吧;
C#代碼如下:
public class TabItemClose : TabItem { static TabItemClose() { DefaultStyleKeyProperty.OverrideMetadata(typeof(TabItemClose), new FrameworkPropertyMetadata(typeof(TabItemClose))); } private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { d.SetValue(e.Property, e.NewValue); } /// <summary> /// 是否可以關(guān)閉 /// </summary> public bool IsCanClose { get { return (bool)GetValue(IsCanCloseProperty); } set { SetValue(IsCanCloseProperty, value); } } public static readonly DependencyProperty IsCanCloseProperty = DependencyProperty.Register("IsCanClose", typeof(bool), typeof(TabItemClose), new PropertyMetadata(true, OnPropertyChanged)); /// <summary> /// 關(guān)閉的圖標(biāo) /// </summary> public ImageSource CloseIcon { get { return (ImageSource)GetValue(CloseIconProperty); } set { SetValue(CloseIconProperty, value); } } public static readonly DependencyProperty CloseIconProperty = DependencyProperty.Register("CloseIcon", typeof(ImageSource), typeof(TabItemClose), new PropertyMetadata(null, OnPropertyChanged)); /// <summary> /// 正常背景色 /// </summary> public SolidColorBrush NormalBackground { get { return (SolidColorBrush)GetValue(NormalBackgroundProperty); } set { SetValue(NormalBackgroundProperty, value); } } public static readonly DependencyProperty NormalBackgroundProperty = DependencyProperty.Register("NormalBackground", typeof(SolidColorBrush), typeof(TabItemClose), new PropertyMetadata(null, OnPropertyChanged)); /// <summary> /// 懸浮背景色 /// </summary> public SolidColorBrush OverBackgound { get { return (SolidColorBrush)GetValue(OverBackgoundProperty); } set { SetValue(OverBackgoundProperty, value); } } public static readonly DependencyProperty OverBackgoundProperty = DependencyProperty.Register("OverBackgound", typeof(SolidColorBrush), typeof(TabItemClose), new PropertyMetadata(null, OnPropertyChanged)); /// <summary> /// 選中背景色 /// </summary> public SolidColorBrush SelectedBackgound { get { return (SolidColorBrush)GetValue(SelectedBackgoundProperty); } set { SetValue(SelectedBackgoundProperty, value); } } public static readonly DependencyProperty SelectedBackgoundProperty = DependencyProperty.Register("SelectedBackgound", typeof(SolidColorBrush), typeof(TabItemClose), new PropertyMetadata(null, OnPropertyChanged)); /// <summary> /// 默認(rèn)前景色 /// </summary> public SolidColorBrush NormalForeground { get { return (SolidColorBrush)GetValue(NormalForegroundProperty); } set { SetValue(NormalForegroundProperty, value); } } public static readonly DependencyProperty NormalForegroundProperty = DependencyProperty.Register("NormalForeground", typeof(SolidColorBrush), typeof(TabItemClose), new PropertyMetadata(null, OnPropertyChanged)); /// <summary> /// 懸浮前景色 /// </summary> public SolidColorBrush OverForeground { get { return (SolidColorBrush)GetValue(OverForegroundProperty); } set { SetValue(OverForegroundProperty, value); } } public static readonly DependencyProperty OverForegroundProperty = DependencyProperty.Register("OverForeground", typeof(SolidColorBrush), typeof(TabItemClose), new PropertyMetadata(null, OnPropertyChanged)); /// <summary> /// 選中前景色 /// </summary> public SolidColorBrush SelectedForeground { get { return (SolidColorBrush)GetValue(SelectedForegroundProperty); } set { SetValue(SelectedForegroundProperty, value); } } public static readonly DependencyProperty SelectedForegroundProperty = DependencyProperty.Register("SelectedForeground", typeof(SolidColorBrush), typeof(TabItemClose), new PropertyMetadata(null, OnPropertyChanged)); /// <summary> /// 控件圓角 /// </summary> public CornerRadius CornerRadius { get { return (CornerRadius)GetValue(CornerRadiusProperty); } set { SetValue(CornerRadiusProperty, value); } } public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(TabItemClose), new PropertyMetadata(new CornerRadius(0), OnPropertyChanged)); /// <summary> /// 前置Logo /// </summary> public ImageSource LogoIcon { get { return (ImageSource)GetValue(LogoIconProperty); } set { SetValue(LogoIconProperty, value); } } public static readonly DependencyProperty LogoIconProperty = DependencyProperty.Register("LogoIcon", typeof(ImageSource), typeof(TabItemClose), new PropertyMetadata(null, OnPropertyChanged)); /// <summary> /// 前置Logo寬度 /// </summary> public double LogoIconWidth { get { return (double)GetValue(LogoIconWidthProperty); } set { SetValue(LogoIconWidthProperty, value); } } public static readonly DependencyProperty LogoIconWidthProperty = DependencyProperty.Register("LogoIconWidth", typeof(double), typeof(TabItemClose), new PropertyMetadata(double.Parse("0"), OnPropertyChanged)); /// <summary> /// 前置Logo高度 /// </summary> public double LogoIconHeigth { get { return (double)GetValue(LogoIconHeigthProperty); } set { SetValue(LogoIconHeigthProperty, value); } } public static readonly DependencyProperty LogoIconHeigthProperty = DependencyProperty.Register("LogoIconHeigth", typeof(double), typeof(TabItemClose), new PropertyMetadata(double.Parse("0"), OnPropertyChanged)); /// <summary> /// LogoPadding /// </summary> public Thickness LogoPadding { get { return (Thickness)GetValue(LogoPaddingProperty); } set { SetValue(LogoPaddingProperty, value); } } public static readonly DependencyProperty LogoPaddingProperty = DependencyProperty.Register("LogoPadding", typeof(Thickness), typeof(TabItemClose), new PropertyMetadata(new Thickness(0), OnPropertyChanged)); /// <summary> /// 關(guān)閉item事件 /// </summary> public event RoutedEventHandler CloseItem { add { AddHandler(CloseItemEvent, value); } remove { RemoveHandler(CloseItemEvent, value); } } public static readonly RoutedEvent CloseItemEvent = EventManager.RegisterRoutedEvent("CloseItem", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TabItemClose)); /// <summary> /// 關(guān)閉項(xiàng)的右鍵菜單 /// </summary> public ContextMenu ItemContextMenu { get; set; } Border ItemBorder; public override void OnApplyTemplate() { base.OnApplyTemplate(); ItemBorder = Template.FindName("_bordertop", this) as Border; if (ItemContextMenu != null) { ItemBorder.ContextMenu = ItemContextMenu; } } }
這里面我們添加了很多擴(kuò)展功能,包括右鍵菜單,圖標(biāo)顯示和控件圓角,以及各種背景色屬性。
然后為TabItemClose設(shè)置樣式
<Style TargetType="{x:Type local:TabItemClose}"> <Setter Property="HorizontalContentAlignment" Value="Stretch"/> <Setter Property="VerticalContentAlignment" Value="Stretch"/> <Setter Property="Foreground" Value="#666666"/> <Setter Property="Margin" Value="0 0 0 0"/> <Setter Property="Padding" Value="0"/> <Setter Property="BorderThickness" Value="0"/> <Setter Property="CloseIcon" Value="/Images/close2.png"/> <Setter Property="NormalBackground" Value="White"/> <Setter Property="OverBackgound" Value="#33ca5100"/> <Setter Property="SelectedBackgound" Value="#ca5100"/> <Setter Property="NormalForeground" Value="#555558"/> <Setter Property="OverForeground" Value="White"/> <Setter Property="SelectedForeground" Value="White"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:TabItemClose}"> <Border x:Name="_bordertop" Width="{TemplateBinding Width}" MaxWidth="{TemplateBinding MaxWidth}" Height="{TemplateBinding Height}" CornerRadius="{TemplateBinding CornerRadius}" Background="{TemplateBinding NormalBackground}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" ToolTip="{TemplateBinding Header}" > <DockPanel> <Image x:Name="_logo" DockPanel.Dock="Left" Visibility="Visible" Margin="{TemplateBinding LogoPadding}" Source="{TemplateBinding LogoIcon}" VerticalAlignment="Center" HorizontalAlignment="Center" Stretch="Uniform" Width="{TemplateBinding LogoIconWidth}" Height="{TemplateBinding LogoIconHeigth}" /> <Grid Name="_grid" SnapsToDevicePixels="True"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition x:Name="_col_close" Width="20" /> </Grid.ColumnDefinitions> <Border Grid.ColumnSpan="2" Background="White" Opacity="0"/> <TextBlock x:Name="_txt" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" Margin="3 0 3 0" Foreground="{TemplateBinding NormalForeground}" TextAlignment="Center" HorizontalAlignment="Center" Text="{TemplateBinding Header}" /> <Grid x:Name="_gridclose" Grid.Column="1" > <Border x:Name="_borderbg" Background="Black" Opacity="0" /> <local:ButtonEx x:Name="PART_Close_TabItem" HorizontalAlignment="Center" VerticalAlignment="Center" Background="Transparent" Visibility="Visible" Icon="{TemplateBinding CloseIcon}" ButtonType="Icon" /> </Grid> </Grid> </DockPanel> </Border> <ControlTemplate.Triggers> <Trigger Property="LogoIcon" Value="{x:Null}"> <Setter TargetName="_logo" Property="Visibility" Value="Collapsed" /> </Trigger> <Trigger Property="IsCanClose" Value="false"> <Setter TargetName="_gridclose" Property="Visibility" Value="Collapsed"/> <Setter TargetName="_col_close" Property="Width" Value="0"/> </Trigger> <Trigger Property="IsSelected" Value="true"> <Setter TargetName="_bordertop" Property="Background" Value="{Binding SelectedBackgound,RelativeSource={RelativeSource TemplatedParent}}" /> <Setter TargetName="_txt" Property="Foreground" Value="{Binding SelectedForeground,RelativeSource={RelativeSource TemplatedParent}}"/> </Trigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsMouseOver" Value="true"/> <Condition Property="IsSelected" Value="false"/> </MultiTrigger.Conditions> <Setter TargetName="_txt" Property="Foreground" Value="{Binding OverForeground,RelativeSource={RelativeSource TemplatedParent}}"/> <Setter TargetName="_bordertop" Property="Background" Value="{Binding OverBackgound,RelativeSource={RelativeSource TemplatedParent}}"/> </MultiTrigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
這里面使用了一個(gè)close的圖標(biāo)
TabControl的圖標(biāo)可設(shè)置可不設(shè)置,看自己需要。
這里面還用到了前面講的控件ButtonEx,定義方法我就不重復(fù)贅述了。大家可以通過(guò)這個(gè)鏈接跳轉(zhuǎn)查看:http://www.dbjr.com.cn/article/138475.htm。ButtonEx.cs里面還要添加幾個(gè)方法用來(lái)支持關(guān)閉TabItem:
protected override void OnClick() { base.OnClick(); if (!string.IsNullOrEmpty(Name) && Name == "PART_Close_TabItem") { TabItemClose itemclose = FindVisualParent<TabItemClose>(this); (itemclose.Parent as TabControl).Items.Remove(itemclose); RoutedEventArgs args = new RoutedEventArgs(TabItemClose.CloseItemEvent, itemclose); itemclose.RaiseEvent(args); } } public static T FindVisualParent<T>(DependencyObject obj) where T : class { while (obj != null) { if (obj is T) return obj as T; obj = VisualTreeHelper.GetParent(obj); } return null; }
引用示例:
<Grid Background="#858586"> <TabControl Foreground="Black" Width="300" Height="200" Background="Transparent" BorderBrush="Transparent" BorderThickness="0"> <local:TabItemClose Cursor="Hand" Header="音樂(lè)電臺(tái)" Height="20" Width="100"> <Grid Background="#aaffffff"> <TextBlock Text="音樂(lè)電臺(tái)" VerticalAlignment="Center" HorizontalAlignment="Center"/> </Grid> </local:TabItemClose> <local:TabItemClose Cursor="Hand" Header="Mv電臺(tái)" Height="20" Width="100"> <Grid Background="#aaffffff"> <TextBlock Text="Mv電臺(tái)" VerticalAlignment="Center" HorizontalAlignment="Center"/> </Grid> </local:TabItemClose> </TabControl> </Grid>
效果如下:
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
- WPF自定義控件和樣式之自定義按鈕(Button)
- 超炫酷的WPF實(shí)現(xiàn)Loading控件效果
- WPF的ListView控件自定義布局用法實(shí)例
- 在WPF中動(dòng)態(tài)加載XAML中的控件實(shí)例代碼
- C# 使用WPF 用MediaElement控件實(shí)現(xiàn)視頻循環(huán)播放
- WPF自定義TreeView控件樣式實(shí)現(xiàn)QQ聯(lián)系人列表效果
- WPF實(shí)現(xiàn)ScrollViewer滾動(dòng)到指定控件處
- WPF實(shí)現(xiàn)帶全選復(fù)選框的列表控件
- WPF開(kāi)發(fā)技巧之花式控件功能擴(kuò)展詳解
相關(guān)文章
WPF實(shí)現(xiàn)在控件上顯示Loading等待動(dòng)畫(huà)的方法詳解
這篇文章主要介紹了WPF 如何在控件上顯示 Loading 等待動(dòng)畫(huà),文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定幫助,需要的可以參考一下2023-03-03C#中使用Override和New關(guān)鍵字進(jìn)行版本控制
在?C#?中,override?和?new?關(guān)鍵字用于控制類之間的成員方法的隱藏和重寫,理解它們之間的差異和使用場(chǎng)景對(duì)于設(shè)計(jì)靈活且易于維護(hù)的代碼至關(guān)重要,在這篇博客中,我們將詳細(xì)探討這兩個(gè)關(guān)鍵字的用法,并通過(guò)示例來(lái)說(shuō)明它們的實(shí)際應(yīng)用,需要的朋友可以參考下2024-10-10C# HttpClient Cookie驗(yàn)證解決方法
本文將詳細(xì)介紹C# HttpClient Cookie驗(yàn)證解決方法,需要了解的朋友可以參考下2012-11-11C# Record構(gòu)造函數(shù)的行為更改詳解
C# 9 中的record類型是僅具有只讀屬性的輕量級(jí)、不可變數(shù)據(jù)類型(或輕量級(jí)類),下面這篇文章主要給大家介紹了關(guān)于C# Record構(gòu)造函數(shù)的行為更改的相關(guān)資料,需要的朋友可以參考下2021-08-08C# 利用AForge實(shí)現(xiàn)攝像頭信息采集
這篇文章主要介紹了C# 如何利用AForge實(shí)現(xiàn)攝像頭信息采集,文中示例代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下2020-07-07