如何使用 WPF 创建带有选项卡指示器的动画选项卡?
How to Create Animated Tabs with Tab Indicator using WPF?
我的 WPF 应用程序中有一个 Tab 控件。而这个 Tab 控件有两个 Tab 项。由于设计目的,我在每个选项卡项目下划线。现在我想为这些选项卡项的下划线设置动画。当我 select 任何此选项卡项时,我只想要一个简单的动画,下划线应该从一个选项卡项快速移动到另一个选项卡项。尽管这些选项卡项之间有一个不错的 space。
我通过控件模板中的文本装饰实现了那些选项卡项的下划线。我对两个选项卡项都使用了自己的自定义控件模板。我在这些选项卡项之间的特定 space 上使用了分隔符。我为选项卡项的那些选项卡 header 的下划线指定了红色。我还为分隔符指定了红色。而且它看起来也像一个动画 Tab 指示器。
我可以使用矩形,但我没有使用它,因为分隔符更轻便。
我知道我必须使用故事板 属性 来淡出分隔符,但我不知道如何应用它。
我想要的是,当我在这两个选项卡项之间切换时,分隔符应该从一侧淡出到另一侧,反之亦然,这样看起来红色下划线通过 space他们之间
这是选项卡项目的控制模板:
<Style x:Key="TabItemGoTwo" TargetType="{x:Type TabItem}">
<Setter Property="Foreground" Value="#939393" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid
x:Name="Root"
ClipToBounds="true"
KeyboardNavigation.TabNavigation="Local"
RenderOptions.BitmapScalingMode="NearestNeighbor"
RenderOptions.ClearTypeHint="Enabled"
SnapsToDevicePixels="true"
UseLayoutRounding="True">
<Border
x:Name="Border"
Margin="0,0,-4,0"
BorderThickness="1,1,1,1"
CornerRadius="2,12,0,0">
<Border.BorderBrush>
<SolidColorBrush Color="#282828" />
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Offset="0.0" Color="#282828" />
<GradientStop Offset="1.0" Color="#282828" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
<ContentPresenter
x:Name="ContentSite"
Margin="0,2,12,2"
HorizontalAlignment="Left"
VerticalAlignment="Center"
ContentSource="Header"
RecognizesAccessKey="True"
RenderOptions.BitmapScalingMode="NearestNeighbor"
RenderOptions.ClearTypeHint="Enabled"
SnapsToDevicePixels="True"
UseLayoutRounding="True" />
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel>
<TextBlock
RenderOptions.EdgeMode="Aliased"
SnapsToDevicePixels="True"
Text="{TemplateBinding Content}"
UseLayoutRounding="True">
<TextBlock.TextDecorations>
<TextDecoration PenOffset="4" PenOffsetUnit="Pixel">
<TextDecoration.Pen>
<Pen Brush="#fe0000" Thickness="3" />
</TextDecoration.Pen>
</TextDecoration>
</TextBlock.TextDecorations>
</TextBlock>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="#fdfdfd" />
<Setter Property="Panel.ZIndex" Value="100" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Root" Property="Background" Value="#282828" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="#fdfdfd" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
这是我的选项卡项代码,该选项卡控件中的分隔符。
<StackPanel Width="645" HorizontalAlignment="Left" Height="460" VerticalAlignment="Top" Margin="-4,59,0,0" UseLayoutRounding="True" >
<TabControl x:Name="MyTabControl" SelectionChanged="MyTabControl_SelectionChanged" BorderThickness="0" Background="#282828" Width="656" HorizontalAlignment="Left" Height="462" VerticalAlignment="Top" Margin="-5,1,-0.2,0" >
<TabItem x:Name="TabItemFirst" Style="{StaticResource TabItemGoTwo}" Header="File manager" Margin="34,0,-26.6,0" Height="24" FontSize="10" VerticalAlignment="Center" UseLayoutRounding="True" RenderOptions.ClearTypeHint="Enabled" RenderOptions.BitmapScalingMode="NearestNeighbor" SnapsToDevicePixels="True" TextOptions.TextFormattingMode="Display" FontFamily="Segoe UI" >
<Grid Background="#222222" Height="433" HorizontalAlignment="Left" VerticalAlignment="Top" Width="645" Margin="0,5,0,0" >
<Label Name="Folder" Content="Folder:" FontSize="10" Foreground="#efefef" Height="20" Width="40" Margin="-571,-367,0,0" FontFamily="Segoe UI" UseLayoutRounding="True" TextOptions.TextFormattingMode="Display" />
<Button Name ="FolderSelect" Width="532" HorizontalAlignment="Left" VerticalAlignment="Top" Height="33" Margin="85,17,0,0" Background="#1a1a1a"
materialDesign:ShadowAssist.ShadowDepth="Depth0" materialDesign:RippleAssist.Feedback="Transparent" BorderThickness="0" UseLayoutRounding="True"
></Button>
<Label Name="ShowFolders" Content=".." Margin="-479,59,0,0" Background="#1a1a1a" Width="168" Height="373" Foreground="#efefef" ></Label>
<Button
Width="65" HorizontalAlignment="Left" Height="25" Background="#FF403D3D" Margin="16,292,0,0"
ToolTip="Resource name: MaterialDesignRaisedButton">
<materialDesign:PackIcon Kind="PlusThick" />
</Button>
<Button
Width="65" HorizontalAlignment="Left" Height="25" Background="#FF403D3D" Margin="82,292,0,0"
ToolTip="Open output folder">
<materialDesign:PackIcon Kind="FolderUpload" />
</Button>
<Label Content="Video recordings:" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="269.2,-22,0,0" Foreground="#efefef" FontSize="10" FontFamily="Segoe UI" UseLayoutRounding="True" TextOptions.TextFormattingMode="Display" />
</Grid>
</TabItem>
<TabItem x:Name="TabItemSecond" Style="{StaticResource TabItemGoTwo}" Header="Preview" FontSize="10" Height="24" Margin="47.4,0,-39.6,0" FontFamily="Segoe UI" VerticalAlignment="Center" UseLayoutRounding="True" RenderOptions.ClearTypeHint="Enabled" RenderOptions.BitmapScalingMode="NearestNeighbor" SnapsToDevicePixels="True" TextOptions.TextFormattingMode="Display" >
<Grid></Grid>
</TabItem>
</TabControl>
</StackPanel>
<StackPanel Height="10" Width="30" Margin="-850,-395,0,0" >
<Separator Height="2" Background="#fe0000" Margin="2,4,2.4,0" SnapsToDevicePixels="True" UseLayoutRounding="True" RenderOptions.ClearTypeHint="Enabled" RenderOptions.BitmapScalingMode="NearestNeighbor" ></Separator>
</StackPanel>
我将你最后的 StackPanel
替换为 Canvas
并使用以下动画代码更新你的 Separator
:
<Canvas>
<Separator Height="2" Width="50" Background="Red" Margin="25,82,4,0" >
<Separator.Style>
<Style TargetType="Separator">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=MyTabControl,Path=SelectedIndex}" Value="1">
<DataTrigger.EnterActions>
<BeginStoryboard Name="MyBeginStoryboard">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="0" To="100" Duration="0:0:1"></DoubleAnimation>
<DoubleAnimation Storyboard.TargetProperty="Width" From="50" To="20" Duration="0:0:1"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard Name="MyBeginStoryboard2">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="100" To="0" Duration="0:0:1"></DoubleAnimation>
<DoubleAnimation Storyboard.TargetProperty="Width" From="30" To="50" Duration="0:0:1"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Separator.Style>
</Separator>
</Canvas>
我的 WPF 应用程序中有一个 Tab 控件。而这个 Tab 控件有两个 Tab 项。由于设计目的,我在每个选项卡项目下划线。现在我想为这些选项卡项的下划线设置动画。当我 select 任何此选项卡项时,我只想要一个简单的动画,下划线应该从一个选项卡项快速移动到另一个选项卡项。尽管这些选项卡项之间有一个不错的 space。
我通过控件模板中的文本装饰实现了那些选项卡项的下划线。我对两个选项卡项都使用了自己的自定义控件模板。我在这些选项卡项之间的特定 space 上使用了分隔符。我为选项卡项的那些选项卡 header 的下划线指定了红色。我还为分隔符指定了红色。而且它看起来也像一个动画 Tab 指示器。
我可以使用矩形,但我没有使用它,因为分隔符更轻便。
我知道我必须使用故事板 属性 来淡出分隔符,但我不知道如何应用它。
我想要的是,当我在这两个选项卡项之间切换时,分隔符应该从一侧淡出到另一侧,反之亦然,这样看起来红色下划线通过 space他们之间
这是选项卡项目的控制模板:
<Style x:Key="TabItemGoTwo" TargetType="{x:Type TabItem}">
<Setter Property="Foreground" Value="#939393" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid
x:Name="Root"
ClipToBounds="true"
KeyboardNavigation.TabNavigation="Local"
RenderOptions.BitmapScalingMode="NearestNeighbor"
RenderOptions.ClearTypeHint="Enabled"
SnapsToDevicePixels="true"
UseLayoutRounding="True">
<Border
x:Name="Border"
Margin="0,0,-4,0"
BorderThickness="1,1,1,1"
CornerRadius="2,12,0,0">
<Border.BorderBrush>
<SolidColorBrush Color="#282828" />
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Offset="0.0" Color="#282828" />
<GradientStop Offset="1.0" Color="#282828" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
<ContentPresenter
x:Name="ContentSite"
Margin="0,2,12,2"
HorizontalAlignment="Left"
VerticalAlignment="Center"
ContentSource="Header"
RecognizesAccessKey="True"
RenderOptions.BitmapScalingMode="NearestNeighbor"
RenderOptions.ClearTypeHint="Enabled"
SnapsToDevicePixels="True"
UseLayoutRounding="True" />
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel>
<TextBlock
RenderOptions.EdgeMode="Aliased"
SnapsToDevicePixels="True"
Text="{TemplateBinding Content}"
UseLayoutRounding="True">
<TextBlock.TextDecorations>
<TextDecoration PenOffset="4" PenOffsetUnit="Pixel">
<TextDecoration.Pen>
<Pen Brush="#fe0000" Thickness="3" />
</TextDecoration.Pen>
</TextDecoration>
</TextBlock.TextDecorations>
</TextBlock>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="#fdfdfd" />
<Setter Property="Panel.ZIndex" Value="100" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Root" Property="Background" Value="#282828" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="#fdfdfd" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
这是我的选项卡项代码,该选项卡控件中的分隔符。
<StackPanel Width="645" HorizontalAlignment="Left" Height="460" VerticalAlignment="Top" Margin="-4,59,0,0" UseLayoutRounding="True" >
<TabControl x:Name="MyTabControl" SelectionChanged="MyTabControl_SelectionChanged" BorderThickness="0" Background="#282828" Width="656" HorizontalAlignment="Left" Height="462" VerticalAlignment="Top" Margin="-5,1,-0.2,0" >
<TabItem x:Name="TabItemFirst" Style="{StaticResource TabItemGoTwo}" Header="File manager" Margin="34,0,-26.6,0" Height="24" FontSize="10" VerticalAlignment="Center" UseLayoutRounding="True" RenderOptions.ClearTypeHint="Enabled" RenderOptions.BitmapScalingMode="NearestNeighbor" SnapsToDevicePixels="True" TextOptions.TextFormattingMode="Display" FontFamily="Segoe UI" >
<Grid Background="#222222" Height="433" HorizontalAlignment="Left" VerticalAlignment="Top" Width="645" Margin="0,5,0,0" >
<Label Name="Folder" Content="Folder:" FontSize="10" Foreground="#efefef" Height="20" Width="40" Margin="-571,-367,0,0" FontFamily="Segoe UI" UseLayoutRounding="True" TextOptions.TextFormattingMode="Display" />
<Button Name ="FolderSelect" Width="532" HorizontalAlignment="Left" VerticalAlignment="Top" Height="33" Margin="85,17,0,0" Background="#1a1a1a"
materialDesign:ShadowAssist.ShadowDepth="Depth0" materialDesign:RippleAssist.Feedback="Transparent" BorderThickness="0" UseLayoutRounding="True"
></Button>
<Label Name="ShowFolders" Content=".." Margin="-479,59,0,0" Background="#1a1a1a" Width="168" Height="373" Foreground="#efefef" ></Label>
<Button
Width="65" HorizontalAlignment="Left" Height="25" Background="#FF403D3D" Margin="16,292,0,0"
ToolTip="Resource name: MaterialDesignRaisedButton">
<materialDesign:PackIcon Kind="PlusThick" />
</Button>
<Button
Width="65" HorizontalAlignment="Left" Height="25" Background="#FF403D3D" Margin="82,292,0,0"
ToolTip="Open output folder">
<materialDesign:PackIcon Kind="FolderUpload" />
</Button>
<Label Content="Video recordings:" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="269.2,-22,0,0" Foreground="#efefef" FontSize="10" FontFamily="Segoe UI" UseLayoutRounding="True" TextOptions.TextFormattingMode="Display" />
</Grid>
</TabItem>
<TabItem x:Name="TabItemSecond" Style="{StaticResource TabItemGoTwo}" Header="Preview" FontSize="10" Height="24" Margin="47.4,0,-39.6,0" FontFamily="Segoe UI" VerticalAlignment="Center" UseLayoutRounding="True" RenderOptions.ClearTypeHint="Enabled" RenderOptions.BitmapScalingMode="NearestNeighbor" SnapsToDevicePixels="True" TextOptions.TextFormattingMode="Display" >
<Grid></Grid>
</TabItem>
</TabControl>
</StackPanel>
<StackPanel Height="10" Width="30" Margin="-850,-395,0,0" >
<Separator Height="2" Background="#fe0000" Margin="2,4,2.4,0" SnapsToDevicePixels="True" UseLayoutRounding="True" RenderOptions.ClearTypeHint="Enabled" RenderOptions.BitmapScalingMode="NearestNeighbor" ></Separator>
</StackPanel>
我将你最后的 StackPanel
替换为 Canvas
并使用以下动画代码更新你的 Separator
:
<Canvas>
<Separator Height="2" Width="50" Background="Red" Margin="25,82,4,0" >
<Separator.Style>
<Style TargetType="Separator">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=MyTabControl,Path=SelectedIndex}" Value="1">
<DataTrigger.EnterActions>
<BeginStoryboard Name="MyBeginStoryboard">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="0" To="100" Duration="0:0:1"></DoubleAnimation>
<DoubleAnimation Storyboard.TargetProperty="Width" From="50" To="20" Duration="0:0:1"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard Name="MyBeginStoryboard2">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" From="100" To="0" Duration="0:0:1"></DoubleAnimation>
<DoubleAnimation Storyboard.TargetProperty="Width" From="30" To="50" Duration="0:0:1"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Separator.Style>
</Separator>
</Canvas>