【翻译】VSM 和触发器

原文:The VisualStateManager and Triggerswindows

Author:工具

  Silverlight 推出了可视化状态管理器( Visual State Manager ),它使得控件模版做者更方便地指定依赖可视化状态的控件外观。WPF Toolkit 附带了一个可视化状态管理器( Visual State Manager ),WPF 的下个版本将会加入 VSM。能够理解地,VisualStateManager 的引进带来了问题:什么时候使用 VSM 代替触发器,什么时候使用触发器会更适合。本博文尝试解决这个问题:更多对如何使用可视化状态管理器( VisualStateManager )的深刻讨论在这里动画

  可视化状态管理器( VisualStateManager )支持 parts 和 states 模型,控件做者使可视化状态在控件模版中形式化的一种方法。可视化状态管理器( VisualStateManager )使控件做者可以管理一个控件的不一样状态而且为设计工具提供了一个方法,好比 Microsoft Blend 支持经过控件的可视化状态自定义它的外观。在 parts 和 states 模型被引进以前,广泛地,当它改变了可视化状态,控件模版做者使用触发器来改变控件的外观。下面的控件模版中,当鼠标悬停在按钮上面或者按钮被按压时,使用触发器来改变按钮的 border 颜色。spa

<ControlTemplate TargetType="Button">
    <Grid>
        <Ellipse Fill="{TemplateBinding BorderBrush}"/>
        <Ellipse x:Name="ButtonShape" 
                 Margin="5" 
                 Fill="{TemplateBinding Background}"/>
        <ContentPresenter HorizontalAlignment="Center"
                          VerticalAlignment="Center"/>
    </Grid>

    <ControlTemplate.Triggers>
        <Trigger Property="IsMouseOver" 
                 Value="True">
            <Setter Property="BorderBrush" 
                    Value="Cyan"/>
        </Trigger>
        <Trigger Property="IsPressed" 
                 Value="True">
            <Setter Property="BorderBrush" 
                    Value="Red"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

  在这个模型中,没有关于什么是可视化状态正式的协议,这里只有定义在控件里的一些用来改变控件外观的属性。 A control that follows the parts and control model proactively communicates its visual states to control template authors.  当一个控件使用可视化状态管理器( VisualStateManager )来改变它的可视化状态,它就指望 控件模版(ControlTemplate )使用 可视化状态管理器( VisualStateManager )来为一个给定的可视化状态指定控件的外观。控件模版做者也能够经过可视化过渡(VisualTransitions)使用自定义可视化状态之间的过渡。可视化过渡(VisualTransitions)使得空间模版做者可以经过改变单个属性改变的时间和区间对单个过渡(transition)进行微调,甚至对在其余状态中没有说起的属性加上动画效果(animate)。下面的例子使用可视化状态管理器( VisualStateManager )而不是触发器来指定控件外观的改变。.net

<ControlTemplate TargetType="Button">
    <Grid>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">

                <VisualStateGroup.Transitions>
                    <!--Take one half second to transition to the MouseOver state.-->
                    <VisualTransition To="MouseOver" 
                                      GeneratedDuration="0:0:0.5" />
                </VisualStateGroup.Transitions>

                <VisualState x:Name="Normal"/>
                <VisualState x:Name="MouseOver">
                    <Storyboard>
                        <ColorAnimation Duration="0" 
                                        Storyboard.TargetName="borderColor" 
                                        Storyboard.TargetProperty="Color" 
                                        To="Cyan"/>
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="Pressed">
                    <Storyboard>
                        <ColorAnimation Duration="0" 
                                        Storyboard.TargetName="borderColor" 
                                        Storyboard.TargetProperty="Color" 
                                        To="Red"/>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <Ellipse>
            <Ellipse.Fill>
                <SolidColorBrush x:Name="borderColor" 
                                 Color="Black"/>
            </Ellipse.Fill>
        </Ellipse>
        <Ellipse x:Name="ButtonShape" 
                 Margin="5" 
                 Fill="{TemplateBinding Background}"/>
        <ContentPresenter HorizontalAlignment="Center"
                          VerticalAlignment="Center"/>
    </Grid>
</ControlTemplate>

  控件经过使用可视化状态管理器( VisualStateManager )并调用  VisualStateManager.GoToState 来改变可视化状态。当这一切发生时,在可视化状态(VisualState)和可视化过渡(VisualTransition)对象中, 可视化状态管理器( VisualStateManager )正确地中止和开始故事板(storyboards),所以按钮的外观正确地改变可视化状态。为此,这里有一个明确的分工:控件做者指定控件的哪一个可视化状态并决定一个控件什么时候进入每个可视化状态;模版做者指定这个控件在每一个可视化状态中的外观。设计

  然而触发器在WPF中并非没用了。你可使用触发器改变控件的外观,这并不对应与一个可视化状态。举个例子,按钮有一个 IsDefault 属性,可是在按钮中没有一个相对应的可视化状态。控件模版做者可能想要指定依赖 IsDefault 的值的按钮外观,这是一个适合用触发器的情景。下面的例子重复了以前的例子,并加入了一个触发器来指定依赖 IsDefault 的值的按钮外观。code

<ControlTemplate TargetType="Button">
    <Grid>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">

                <VisualStateGroup.Transitions>
                    <!--Take one half second to transition to the MouseOver state.-->
                    <VisualTransition To="MouseOver" 
                                      GeneratedDuration="0:0:0.5" />
                </VisualStateGroup.Transitions>

                <VisualState x:Name="Normal"/>
                <VisualState x:Name="MouseOver">
                    <Storyboard>
                        <ColorAnimation Duration="0" 
                                        Storyboard.TargetName="borderColor" 
                                        Storyboard.TargetProperty="Color" 
                                        To="Cyan"/>
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="Pressed">
                    <Storyboard>
                        <ColorAnimation Duration="0" 
                                        Storyboard.TargetName="borderColor" 
                                        Storyboard.TargetProperty="Color" 
                                        To="Red"/>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <Ellipse>
            <Ellipse.Fill>
                <SolidColorBrush x:Name="borderColor" 
                                 Color="Black"/>
            </Ellipse.Fill>
        </Ellipse>
        <Ellipse x:Name="defaultOutline" 
                 Stroke="{TemplateBinding Background}" 
                 StrokeThickness="2" 
                 Margin="2"/>
        <Ellipse x:Name="ButtonShape" 
                 Margin="5" 
                 Fill="{TemplateBinding Background}"/>
        <ContentPresenter HorizontalAlignment="Center"
                          VerticalAlignment="Center"/>
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger Property="IsDefault" 
                 Value="False">
            <Setter TargetName="defaultOutline" 
                    Property="Stroke" 
                    Value="Transparent"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

  按钮中的 IsMouseOver 和 IsPressed 属性依然有效,可是你不该该建立触发器来阻止它们改变按钮的外观。这并不意味这些属性没有用了。这些属性依然能够被应用做者用来在代码中检查控件的可视化状态,甚至当他们使用可视化状态管理器(VisualStateManager)在它们的可视化状态之间过渡时,控件做者应该继续定义用于可视化状态的属性。orm

相关文章
相关标签/搜索