本篇再补充一块内容,就是自定义状态的介绍。
自定义状态用于封装用户控件在各种状态之间切换时的外观变化及其动画效果,方便调用。比如有个用户控件用于实现类似舞台幕布打开和关闭切换的效果,可以创建幕布关闭和幕布打开两个状态并编辑界面及动画,然后调用状态切换,就可以方便地实现幕布打开和关闭效果。下面看演示。
1. 首先创建一个用户控件命名为CurtainControl,打开该用户控件的xaml进行编辑。
2. 在状态面板中,点击添加状态组按钮,将新添加的状态组命名为CurtainControlStateGroup,点击添加状态按钮,添加两个状态,命名为CurtainOpened和CurtainClosed。
3. 点击选择状态面板中的“基本”状态项,将界面中的Grid分为四列,两边的两列为0,中间的两列为*,背景改为白色。在外层Grid内部放入两个Border,分别在中间两列,背景色改为某种径向渐变色(为了演示方便,实际项目可精心设计),加个边的颜色,最好抽取样式。完成后代码如下,
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x:Class="BlendDemo.CurtainControl"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<Style x:Key="CurtainStyle" TargetType="{x:Type Border}">
<Setter Property="Background">
<Setter.Value>
<RadialGradientBrush>
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="#FFFFC1C1" Offset="1"/>
<GradientStop Color="#FF382B2B" Offset="0.223"/>
<GradientStop Color="#FF755959" Offset="0.465"/>
</RadialGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="BorderBrush" Value="#FF00B9FF"/>
<Setter Property="BorderThickness" Value="1"/>
</Style>
</UserControl.Resources>
<Grid Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0"/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition Width="0"/>
</Grid.ColumnDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CurtainControlStateGroup">
<VisualState x:Name="CurtainOpened"/>
<VisualState x:Name="CurtainClosed"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border Grid.Column="1" Style="{DynamicResource CurtainStyle}"/>
<Border Grid.Column="2" Style="{DynamicResource CurtainStyle}"/>
</Grid>
</UserControl>
4. 点击状态面板中的CurtainControlStateGroup状态组的打开FluidLayout按钮(图标为上下两个波浪线),然后选择CurtainOpened状态项,进入动画录制状态。将第一个Border的Grid.Column由1改为0,将第二个Border的Grid.Column由2改为3。
5. 点击选择状态面板中的“基本”状态项,退出动画录制状态。将CurtainControlStateGroup状态组的默认过度时间改为1s。
此时用户控件已经完成,完整代码如下。
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
x:Class ="BlendDemo.CurtainControl"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<Style x:Key="CurtainStyle" TargetType="{x:Type Border}">
<Setter Property="Background">
<Setter.Value>
<RadialGradientBrush>
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="#FFFFC1C1" Offset="1"/>
<GradientStop Color="#FF382B2B" Offset="0.223"/>
<GradientStop Color="#FF755959" Offset="0.465"/>
</RadialGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="BorderBrush" Value="#FF00B9FF"/>
<Setter Property="BorderThickness" Value="1"/>
</Style>
</UserControl.Resources>
<Grid Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0"/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition Width="0"/>
</Grid.ColumnDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CurtainControlStateGroup" ei:ExtendedVisualStateManager.UseFluidLayout="True">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:1"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="CurtainOpened">
<Storyboard>
<Int32AnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Column)" Storyboard.TargetName="border">
<EasingInt32KeyFrame KeyTime="0" Value="0"/>
</Int32AnimationUsingKeyFrames>
<Int32AnimationUsingKeyFrames Storyboard.TargetProperty="(Grid.Column)" Storyboard.TargetName="border1">
<EasingInt32KeyFrame KeyTime="0" Value="3"/>
</Int32AnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="CurtainClosed"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<VisualStateManager.CustomVisualStateManager>
<ei:ExtendedVisualStateManager/>
</VisualStateManager.CustomVisualStateManager>
<Border x:Name="border" Grid.Column="1" Style="{DynamicResource CurtainStyle}"/>
<Border x:Name="border1" Grid.Column="2" Style="{DynamicResource CurtainStyle}"/>
</Grid>
</UserControl>
6. 创建一个空的窗口,并设置为程序启动窗口。在外层Grid中加入两行,第一行为Auto,在其中放两个Button(外面套一个横向的StackPanel),文字改为打开和关闭。第二行为*,放入CurtainControl控件,在资产面板的“项目”分类中找,如果找不到该控件,请先生成项目。
7. 在资产面板中,选择“行为”分类,拖动GoToStateAction到文档大纲面板中的第一个Button上。在属性面板中,点击公共组下面的TargetName属性的美工板元素选取器按钮(圆圈中间有一个黑点),在美工板中选择CurtainControl控件。点击StateName属性的下拉框,选择CurtainOpened状态。第二个Button也执行同样的操作,StateName属性选择CurtainClosed状态。
至此,演示示例已全部完成,Window1的代码如下。
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:BlendDemo"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
x:Class="BlendDemo.Window1"
mc:Ignorable="d"
Title="Window1" Height="322" Width="375">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<local:CurtainControl x:Name="curtainControl" Grid.Row="1"/>
<StackPanel Orientation="Horizontal">
<Button Content="打开">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:GoToStateAction TargetName="curtainControl" StateName="CurtainOpened"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<Button Content="关闭">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:GoToStateAction TargetName="curtainControl" StateName="CurtainClosed"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</StackPanel>
</Grid>
</Window>
界面效果如下,
点击打开和关闭按钮试试效果吧。