Trigger和ViewStateManager的具体比较

本文对比了XAML中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.5Silverlight 5/WP8WinRT(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中也不错,因为在某些时候,开发者又有一种新的选择!

转载于:https://www.cnblogs.com/m7777/p/6084152.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值