Trigger和ViewStateManager的具体比较

ViewStateManager的好处  拥有 GeneratedDuration ,可以很方便的进行几个状态之间的切换过渡动画。

坏处是,在界面加载时只能显示默认效果,通过GoToStateAction 绑定的DataTrigger 必须在界面加载完毕后触发才有效果。

-------下面为转载http://www.th7.cn/Program/net/201212/115057.shtml

    [TemplateVisualState(Name = "Large", GroupName = "SizeStates")]
[TemplateVisualState(Name = "Small", GroupName = "SizeStates")]
[TemplateVisualState(Name = "Inactive", GroupName = "ActiveStates")]
[TemplateVisualState(Name = "Active", GroupName = "ActiveStates")]

目录

  • 1. Trigger的支持
  • 2. 为什么是Trigger?
  • 3. ViewStateManager的支持
  • 4. Trigger和ViewStateManager的具体比较

返回目录

1. Trigger的支持

Trigger是XAML中另一个非常有趣的特性,它就像是在XAML中定义了一个if语句。但是随着后期微软XAML框架的演变,Trigger却逐渐被弱化,让我们先看看Trigger在当前最新XAML框架中的支持状况:

  WPF 4.5 Silverlight 5/WP8 WinRT(Windows 8)
FrameworkElement.Triggers 
(注意这里只支持EventTrigger)
支持 支持 支持
Style.Triggers 支持 不支持 不支持
DataTempate.Triggers 支持 不支持 不支持
ControlTemplate.Triggers 支持 不支持 不支持
Trigger类型 支持 不支持 不支持
EventTrigger类型 支持 支持 支持
DataTrigger类型 支持 不支持 不支持
TriggerBase.Enter/ExitActions 支持 不支持 不支持
BeginStoryboard TriggerAction 支持 支持 支持

看到了吧,Trigger在后期微软XAML框架中已经被大大削减,说实话只有WPF才能算上是支持Trigger的,而Silverlight/WinRT也就仅仅是在FrameworkElement的Trigges属性中支持BeginStoryboard这个TriggerAction罢了。

注意:

Microsoft Expression Blend SDK可以提供额外的对Trigger相关类型的支持。比如众所周知的System.Windows.Interactivity.dll。

返回目录

2. 为什么是Trigger?

OK,那么为什么Trigger在后期XAML框架混的这么惨呢?

我个人认为两点:

1:Trigger本身不是100%必须的,而后期的XAML框架显然很重视性能和体积,因此某些不是100%需要的东西就可能被剪掉。

比如模板中的Trigger可以通过定义Converter甚至是DataTemplateSelector代替,而Style中的Trigger通常比较少见,即便有需求也可以直接写在背后控件属性逻辑上,可以不放在XAML中。

2:Trigger多应用在动画定义上,在这一点上。从上面可以看到,EventTrigger和BeginStoryboard都被现有XAML框架所支持。不过在控件模板这种对动画定义需求比较高的情况下,BeginStoryboard很力不从心,而ViewStateManager在这里则完胜Trigger。

返回目录

3. ViewStateManager的支持

注意:

XAML中的ViewState和ASP.NET中的ViewState概念不一样,ASP.NET中的ViewState主要是指数据在无状态协议中的保留问题。而XAML中的ViewState指控件在不同状态下的外表定义。

ViewStateManager只有在某些旧的XAML框架中不支持,新的XAML框架都是很好地支持它的。

不支持ViewStateManager的XAML框架:

WPF 3.0

WPF 3.5

Silverlight 1

Silverlight 2

支持ViewStateManager的XAML框架:

WPF 4 +

Silverlight 3 +

Windows Phone 7.0 +

WinRT

可以看到,VisualStateManager基本上已经是任何XAML框架定义控件模板的标准了。

返回目录

4. Trigger和ViewStateManager的具体比较

接下来我们就来直接来比较一下Trigger和ViewStateManager的风格。我们就用最常见的操作:“控件模板”定义做比较。这也是他们的直接冲突领域。现在我们就定义一个最简单的Button的控件模板,具体规格如下:

1. 颜色默认是蓝色,鼠标指向时变成绿色,点击后变成灰色。

2. 要求点击后动画时长0.1秒,其他统一0.5秒。

注意:

下方代码统一以WPF环境做示例。因为WPF是唯一的既完全支持Trigger也支持ViewStateManager的XAML框架。

使用ViewStateManager方式:

1. 定义ViewStateGroup。

2. 定义具体ViewState

3. 添加Storyboard

4. 需要的话,定义Transition。

XAML:

<Button Content="Mgen">

<Button.Template>

<ControlTemplate TargetType="Button">

<Border Name="border"

Background="LightBlue">

<ContentPresenter Content="{TemplateBinding Content}"/>

<VisualStateManager.VisualStateGroups>

<!-- 普通状态 -->

<VisualStateGroup x:Name="CommonStates">

<!-- 定义时常 -->

<VisualStateGroup.Transitions>

<VisualTransition GeneratedDuration="0:0:0.5"/>

<VisualTransition GeneratedDuration="0:0:0.1" To="Pressed"/>

</VisualStateGroup.Transitions>

<!-- 定义三种状态的Storyboard -->

<VisualState x:Name="Normal"/>

<VisualState x:Name="MouseOver">

<Storyboard>

<ColorAnimation Storyboard.TargetName="border"

Storyboard.TargetProperty="Background.Color"

Duration="0"

To="Green"/>

</Storyboard>

</VisualState>

<VisualState x:Name="Pressed">

<Storyboard>

<ColorAnimation Storyboard.TargetName="border"

Storyboard.TargetProperty="Background.Color"

Duration="0"

To="Gray"/>

</Storyboard>

</VisualState>

</VisualStateGroup>

</VisualStateManager.VisualStateGroups>

</Border>

</ControlTemplate>

</Button.Template>

</Button>

而使用Trigger的方式:

注意:

尽管WPF对Trigger和ViewStateManager都完全支持。但是在WPF 4后,还是推荐使用ViewStateManager的方式定义模板。

使用Trigger定义,我们不得不面对如下麻烦:

1. 选择Trigger类型和对应属性,比如我们使用普通Trigger对象,和Button的IsPressed属性和IsMouseOver来手动判断状态。

2. 根据Trigger类型执行操作,如果使用Trigger.Setters,是具有自动还原功能的,如果使用EnterActions,如果想进行还原操作,必须设置ExitActions。对于EventTrigger,只能使用Actions属性。

3. 使用BeginStoryboard执行Storyboard,这里没有VisualStateManager模式中的GeneratedDuration,一切都得自己定义。

XAML:

<Button Content="Mgen">

<Button.Template>

<ControlTemplate TargetType="Button">

<Border Name="border" Background="LightBlue">

<ContentPresenter/>

</Border>

<!-- 定义Trigger -->

<ControlTemplate.Triggers>

<!-- 鼠标进入的设置和还原动画 -->

<Trigger Property="IsMouseOver" Value="True">

<Trigger.EnterActions>

<BeginStoryboard>

<Storyboard>

<ColorAnimation Storyboard.TargetName="border"

Storyboard.TargetProperty="Background.Color"

To="Green"

Duration="0:0:0.5"/>

</Storyboard>

</BeginStoryboard>

</Trigger.EnterActions>

<Trigger.ExitActions>

<BeginStoryboard>

<Storyboard>

<ColorAnimation Storyboard.TargetName="border"

Storyboard.TargetProperty="Background.Color"

Duration="0:0:0.5"/>

</Storyboard>

</BeginStoryboard>

</Trigger.ExitActions>

</Trigger>

<!-- 鼠标按下的设置和还原动画 -->

<Trigger Property="IsPressed" Value="True">

<Trigger.EnterActions>

<BeginStoryboard>

<Storyboard>

<ColorAnimation Storyboard.TargetName="border"

Storyboard.TargetProperty="Background.Color"

To="Gray"

Duration="0:0:0.1"/>

</Storyboard>

</BeginStoryboard>

</Trigger.EnterActions>

<Trigger.ExitActions>

<BeginStoryboard>

<Storyboard>

<ColorAnimation Storyboard.TargetName="border"

Storyboard.TargetProperty="Background.Color"

Duration="0:0:0.5"/>

</Storyboard>

</BeginStoryboard>

</Trigger.ExitActions>

</Trigger>

</ControlTemplate.Triggers>

</ControlTemplate>

</Button.Template>

</Button>

结果很明显,使用Trigger和ViewStateManager相比,Trigger的方式更原始,可能会依靠多种Trigger的多种执行方式来完成设置操作,动画定义较繁琐。而ViewStateManager,则是为了克服如上缺点而生。

当然,ViewStateManager也有其不好的一面,有些时候,特别是不需要动画的时候,ViewStateManager只能还是使用动画的模式硬生生地进行非动画操作。比如我们创建一个简单的CheckBox的控件模板。当选中后显示“真”,未选时显示“假”。

使用ViewStateManager方式。我们还得定义Storyboard,只不过是用ObjectAnimationUsingKeyFrames。XAML:

<CheckBox IsChecked="False">

<CheckBox.Template>

<ControlTemplate TargetType="CheckBox">

<Border>

<TextBlock Text="真" Name="textBlock"/>

<VisualStateManager.VisualStateGroups>

<VisualStateGroup Name="CheckStates">

<VisualState Name="Checked"/>

<VisualState Name="Unchecked">

<Storyboard>

<ObjectAnimationUsingKeyFrames Duration="0"

Storyboard.TargetName="textBlock"

Storyboard.TargetProperty="Text">

<DiscreteObjectKeyFrame KeyTime="0"

Value="假"/>

</ObjectAnimationUsingKeyFrames>

</Storyboard>

</VisualState>

</VisualStateGroup>

</VisualStateManager.VisualStateGroups>

</Border>

</ControlTemplate>

</CheckBox.Template>

</CheckBox>

这个时候,我们就该想念Trigger,一个再简单不过的Trigger和一个Setter就实现了上述功能,既简单可读性还高,XAML:

<CheckBox IsChecked="False">

<CheckBox.Template>

<ControlTemplate TargetType="CheckBox">

<Border>

<TextBlock Text="真" Name="textBlock"/>

</Border>

<ControlTemplate.Triggers>

<Trigger Property="IsChecked" Value="False">

<Setter TargetName="textBlock"

Property="Text"

Value="假"/>

</Trigger>

</ControlTemplate.Triggers>

</ControlTemplate>

</CheckBox.Template>

</CheckBox>

当然,多数情况下VisualStateManager还是完胜Trigger方式的,毕竟有动画的控件模板更受欢迎!不过如果Trigger被加入到Silverlight和WinRT中也不错,因为在某些时候,开发者又有一种新的选择!

上一篇:Invitation Cards(邻接表+逆向建图+SPFA)


下一篇:Python之路【第十六篇】Django基础