自定义样式效果如下:
整体实现思路首先自定义UTabControl、然后自定义TabItem
1、UTabControl.cs 代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace YOI.Controls
{
public class UTabControl : TabControl
{
static UTabControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(UTabControl), new FrameworkPropertyMetadata(typeof(UTabControl)));
}
/// <summary>
/// 方向枚举
/// </summary>
public enum OrientationEnum
{
Left,
Right,
Middle
}
public HorizontalAlignment TabHorizontalAlignment
{
get { return (HorizontalAlignment)GetValue(TabHorizontalAlignmentProperty); }
set {
SetValue(TabHorizontalAlignmentProperty, value);
}
}
public static readonly DependencyProperty TabHorizontalAlignmentProperty =
DependencyProperty.Register("TabHorizontalAlignment", typeof(HorizontalAlignment), typeof(UTabControl), new PropertyMetadata(HorizontalAlignment.Left, TabHorizontalAlignmentChanged));
private static void TabHorizontalAlignmentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
object oldValue = (object)e.OldValue;
object newValue = (object)e.NewValue;
var uTabControl = (UTabControl)d;
if (oldValue != newValue)
{
switch (newValue)
{
case HorizontalAlignment.Right:
uTabControl.TabHorizontalAlignment = HorizontalAlignment.Right;
break;
case HorizontalAlignment.Center:
uTabControl.TabHorizontalAlignment = HorizontalAlignment.Center;
break;
case HorizontalAlignment.Left:
uTabControl.TabHorizontalAlignment = HorizontalAlignment.Left;
break;
default:
break;
}
}
}
}
}
2、UTabControl模板资源样式
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MotionControls.Controls">
<Style TargetType="{x:Type local:UTabControl}">
<Setter Property="Padding" Value="1" />
<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"
KeyboardNavigation.TabNavigation="Local"
SnapsToDevicePixels="True">
<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"
Grid.Row="0"
Grid.Column="0"
Margin="0"
HorizontalAlignment="{Binding TabHorizontalAlignment, RelativeSource={RelativeSource AncestorType=local:UTabControl, Mode=FindAncestor}}"
Panel.ZIndex="1"
Background="Transparent"
IsItemsHost="True"
KeyboardNavigation.TabIndex="1" />
<Line
Margin="0,0,0,1"
VerticalAlignment="Bottom"
SnapsToDevicePixels="True"
Stroke="Gray"
StrokeThickness="0.1"
X1="0"
X2="{Binding ActualWidth, RelativeSource={RelativeSource Self}}" />
<Border
x:Name="ContentPanel"
Grid.Row="1"
Grid.Column="0"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
KeyboardNavigation.DirectionalNavigation="Contained"
KeyboardNavigation.TabIndex="2"
KeyboardNavigation.TabNavigation="Local">
<ContentPresenter
x:Name="PART_SelectedContentHost"
Margin="0"
Content="{TemplateBinding SelectedContent}"
ContentSource="SelectedContent"
ContentStringFormat="{TemplateBinding SelectedContentStringFormat}"
ContentTemplate="{TemplateBinding SelectedContentTemplate}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="TabStripPlacement" Value="Bottom">
<Setter TargetName="HeaderPanel" Property="Grid.Row" Value="1" />
<Setter TargetName="ContentPanel" Property="Grid.Row" Value="0" />
<Setter TargetName="RowDefinition0" Property="Height" Value="*" />
<Setter TargetName="RowDefinition1" Property="Height" Value="Auto" />
</Trigger>
<Trigger Property="TabStripPlacement" Value="Left">
<Setter TargetName="HeaderPanel" Property="Grid.Row" Value="0" />
<Setter TargetName="ContentPanel" Property="Grid.Row" Value="0" />
<Setter TargetName="HeaderPanel" Property="Grid.Column" Value="0" />
<Setter TargetName="ContentPanel" Property="Grid.Column" Value="1" />
<Setter TargetName="ColumnDefinition0" Property="Width" Value="Auto" />
<Setter TargetName="ColumnDefinition1" Property="Width" Value="*" />
<Setter TargetName="RowDefinition0" Property="Height" Value="*" />
<Setter TargetName="RowDefinition1" Property="Height" Value="0" />
</Trigger>
<Trigger Property="TabStripPlacement" Value="Right">
<Setter TargetName="HeaderPanel" Property="Grid.Row" Value="0" />
<Setter TargetName="ContentPanel" Property="Grid.Row" Value="0" />
<Setter TargetName="HeaderPanel" Property="Grid.Column" Value="1" />
<Setter TargetName="ContentPanel" Property="Grid.Column" Value="0" />
<Setter TargetName="ColumnDefinition0" Property="Width" Value="*" />
<Setter TargetName="ColumnDefinition1" Property="Width" Value="Auto" />
<Setter TargetName="RowDefinition0" Property="Height" Value="*" />
<Setter TargetName="RowDefinition1" Property="Height" Value="0" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="templateRoot" Property="TextElement.Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
3、UTabItem 代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace YOI.Controls
{
public class UTabItem : TabItem
{
static UTabItem()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(UTabItem), new FrameworkPropertyMetadata(typeof(UTabItem)));
}
/// <summary>
/// 选中字体颜色
/// </summary>
public SolidColorBrush ActiveForeground
{
get { return (SolidColorBrush)GetValue(ActiveForegroundProperty); }
set { SetValue(ActiveForegroundProperty, value); }
}
/// <summary>
/// 未选中字体颜色
/// </summary>
[Category("自定义"), Description("该属性用于调整内部文字的未选中字体颜色")]
public SolidColorBrush InactiveForeground
{
get { return (SolidColorBrush)GetValue(InactiveForegroundProperty); }
set { SetValue(InactiveForegroundProperty, value); }
}
/// <summary>
/// 选中字体颜色
/// </summary>
public SolidColorBrush ActiveIndicatorColor
{
get { return (SolidColorBrush)GetValue(ActiveIndicatorColorProperty); }
set { SetValue(ActiveIndicatorColorProperty, value); }
}
public static readonly DependencyProperty ActiveIndicatorColorProperty =
DependencyProperty.Register("ActiveIndicatorColor", typeof(SolidColorBrush), typeof(UTabItem), new PropertyMetadata(new SolidColorBrush(Color.FromRgb(172, 172, 172))));
public static readonly DependencyProperty InactiveForegroundProperty =
DependencyProperty.Register("InactiveForeground", typeof(SolidColorBrush), typeof(UTabItem), new PropertyMetadata(new SolidColorBrush(Color.FromRgb(172, 172, 172))));
public static readonly DependencyProperty ActiveForegroundProperty =
DependencyProperty.Register("ActiveForeground", typeof(SolidColorBrush), typeof(UTabItem), new PropertyMetadata(new SolidColorBrush(Color.FromRgb(67, 67, 68))));
}
}
4、UTabItem 模板资源样式
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MotionControls.Controls">
<Style TargetType="{x:Type local:UTabItem}">
<Setter Property="FontSize" Value="16" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid
x:Name="templateRoot"
Background="{TemplateBinding Background}"
SnapsToDevicePixels="true">
<Border
x:Name="mainBorder"
Margin="{TemplateBinding Margin}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="0"
CornerRadius="1" />
<Rectangle
x:Name="Indicator"
Width="25"
Height="2.5"
VerticalAlignment="Bottom"
RadiusX="2.5"
RadiusY="2.5" />
<Grid>
<TextBlock
x:Name="txt"
Padding="{TemplateBinding Padding}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Cursor="Hand"
FontWeight="{TemplateBinding FontWeight}"
Foreground="{Binding InactiveForeground, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Text="{TemplateBinding Header}"
TextTrimming="CharacterEllipsis"
ToolTip="{TemplateBinding Header}"
Visibility="Visible" />
</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 TargetName="txt" Property="Foreground" Value="{DynamicResource TextPrimaryColor}" />
</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 TargetName="templateRoot" Property="Opacity" 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 local:UTabControl}}}" Value="Top" />
</MultiDataTrigger.Conditions>
<Setter Property="Panel.ZIndex" Value="1" />
<Setter TargetName="txt" Property="Foreground" Value="{Binding ActiveForeground, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
<!--<Setter TargetName="mainBorder" Property="Background" Value="{DynamicResource PrimaryBlueColor}" />-->
<!--<Setter TargetName="mainBorder" Property="Opacity" Value="0.8" />-->
<Setter TargetName="Indicator" Property="Fill" Value="{Binding ActiveIndicatorColor, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
<!--<Setter TargetName="mainBorder" Property="BorderThickness" Value="0,0,0,2" />-->
<MultiDataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="Indicator"
Storyboard.TargetProperty="Width"
From="25"
To="40"
Duration="0:0:0.3" />
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.EnterActions>
<MultiDataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="Indicator"
Storyboard.TargetProperty="Width"
From="40"
To="25"
Duration="0:0:0.3" />
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.ExitActions>
</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 local:UTabControl}}}" Value="Left" />
</MultiDataTrigger.Conditions>
<Setter Property="Panel.ZIndex" Value="1" />
<Setter TargetName="txt" Property="Foreground" Value="{Binding ActiveForeground, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
<!--<Setter TargetName="mainBorder" Property="Background" Value="{DynamicResource PrimaryBlueColor}" />-->
<!--<Setter TargetName="mainBorder" Property="Opacity" Value="0.8" />-->
<Setter TargetName="Indicator" Property="Fill" Value="{Binding ActiveIndicatorColor, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
<!--<Setter TargetName="mainBorder" Property="BorderThickness" Value="0,0,0,2" />-->
<MultiDataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="Indicator"
Storyboard.TargetProperty="Width"
From="25"
To="40"
Duration="0:0:0.3" />
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.EnterActions>
<MultiDataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="Indicator"
Storyboard.TargetProperty="Width"
From="40"
To="25"
Duration="0:0:0.3" />
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.ExitActions>
</MultiDataTrigger>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
5、调用方式
<YOI:UTabControl
Width="Auto"
Height="Auto"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="{DynamicResource PrimaryBackgroundColor}"
BorderBrush="Transparent"
BorderThickness="0,0,0,0"
TabHorizontalAlignment="Center"
TabStripPlacement="Top">
<YOI:UTabItem
Width="100"
Height="38"
VerticalAlignment="Top"
ActiveForeground="{DynamicResource TextBlueColor}"
ActiveIndicatorColor="{DynamicResource TextBlueColor}"
Background="{DynamicResource TextTransparentColor}"
BorderBrush="{DynamicResource TextTransparentColor}"
Foreground="{DynamicResource TextWhiteColor}"
Header="参数1"
InactiveForeground="{DynamicResource TextGrayColor}">
<Grid
Margin="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="{DynamicResource SecundaryGrayColor}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="544*" />
<ColumnDefinition Width="20*" />
<ColumnDefinition Width="121*" />
<ColumnDefinition Width="100*" />
<ColumnDefinition Width="213*" />
</Grid.ColumnDefinitions>
<ContentControl Grid.ColumnSpan="5" prism:RegionManager.RegionName="{x:Static ext:PrismManager.MotionViewRegionName}" />
</Grid>
</YOI:UTabItem>
</YOI:UTabControl>