VisualStateManager和生成的转换

can*_*ork 9 wpf animation visualstatemanager transitions vsm

就在我认为我理解的时候VisualStateManager,有些东西证明我错了.

我正在使用WPF 4,我试图简单地将鼠标放大,然后在鼠标离开时将其缩小.我想我只是在a中定义每个状态VisualStateGroup然后VisualTransition用a 指定a GeneratedDuration:

<Border x:Name="PART_Root" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" RenderTransformOrigin="0.5,0.5">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup Name="CommonStates">
            <VisualStateGroup.Transitions>
                <VisualTransition GeneratedDuration="0:0:1"/>
            </VisualStateGroup.Transitions>

            <VisualState Name="Normal"/>

            <VisualState Name="MouseOver">
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="scaleTransform" Storyboard.TargetProperty="ScaleX" To="1.5" Duration="0"/>
                    <DoubleAnimation Storyboard.TargetName="scaleTransform" Storyboard.TargetProperty="ScaleY" To="1.5" Duration="0"/>
                </Storyboard>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>

    <Border.RenderTransform>
        <ScaleTransform x:Name="scaleTransform" ScaleX="1" ScaleY="1"/>
    </Border.RenderTransform>

    <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
Run Code Online (Sandbox Code Playgroud)

由于我有一个全能VisualTransitionGeneratedDuration,我期待VSM生成中间动画.也就是说,鼠标悬停在控件上应该在ScaleTransform1秒内将属性设置为1到1.5.与mousing相同.相反,延迟1秒,然后ScaleTransform属性立即捕捉到1.5或回到1.

如果我手动指定转换如下,那么我得到所需的行为:

<VisualStateGroup.Transitions>
    <VisualTransition From="Normal" To="MouseOver">
        <Storyboard>
            <DoubleAnimation Storyboard.TargetName="scaleTransform" Storyboard.TargetProperty="ScaleX" To="1.5" Duration="{StaticResource MouseEnterDuration}"/>
            <DoubleAnimation Storyboard.TargetName="scaleTransform" Storyboard.TargetProperty="ScaleY" To="1.5" Duration="{StaticResource MouseEnterDuration}"/>
        </Storyboard>
    </VisualTransition>

    <VisualTransition From="MouseOver" To="Normal">
        <Storyboard>
            <DoubleAnimation Storyboard.TargetName="scaleTransform" Storyboard.TargetProperty="ScaleX" To="1" Duration="{StaticResource MouseLeaveDuration}"/>
            <DoubleAnimation Storyboard.TargetName="scaleTransform" Storyboard.TargetProperty="ScaleY" To="1" Duration="{StaticResource MouseLeaveDuration}"/>
        </Storyboard>
    </VisualTransition>
</VisualStateGroup.Transitions>
Run Code Online (Sandbox Code Playgroud)

但为什么我必须这样做?我认为生成转换的重点在于,转换将是生成的.我在这里误解了什么?

更新:根据Rick的回答,Blend生成的东西确实有用.因此,向后工作我确定我确实是ScaleTransform直接引用而不是通过UIElement它包含它的事实.我将我的XAML更改为以下内容,它按预期工作:

<Border x:Name="PART_Root" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" RenderTransformOrigin="0.5,0.5">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup Name="CommonStates">
            <VisualStateGroup.Transitions>
                <VisualTransition From="Normal" To="MouseOver" GeneratedDuration="{StaticResource MouseEnterDuration}"/>

                <VisualTransition From="MouseOver" To="Normal" GeneratedDuration="{StaticResource MouseLeaveDuration}"/>
            </VisualStateGroup.Transitions>

            <VisualState Name="Normal"/>

            <VisualState Name="MouseOver">
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="PART_Root" Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)" To="{StaticResource MouseOverScale}" Duration="0"/>
                    <DoubleAnimation Storyboard.TargetName="PART_Root" Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)" To="{StaticResource MouseOverScale}" Duration="0"/>
                </Storyboard>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>

    <Border.RenderTransform>
        <ScaleTransform/>
    </Border.RenderTransform>

    <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
Run Code Online (Sandbox Code Playgroud)

看似荒谬(和一个明显的错误),但它的工作原理.

谢谢

Ric*_*key 7

我不能说我完全理解为什么它不能按照我们期望的方式工作,但在这些情况下我们可以使用Expression Blend来执行任务并查看它产生的标记.我已经完成了这个,这是一个基于你的样本的工作示例:

<Grid>
    <Grid.Resources>
        <Style x:Key="ButtonStyle1" TargetType="{x:Type Button}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Border x:Name="PART_Root" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" RenderTransformOrigin="0.5,0.5">
                            <Border.RenderTransform>
                                <TransformGroup>
                                    <ScaleTransform/>
                                    <SkewTransform/>
                                    <RotateTransform/>
                                    <TranslateTransform/>
                                </TransformGroup>
                            </Border.RenderTransform>
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup Name="CommonStates">
                                    <VisualStateGroup.Transitions>
                                        <VisualTransition GeneratedDuration="0:0:1"/>
                                    </VisualStateGroup.Transitions>
                                    <VisualState Name="Normal"/>
                                    <VisualState x:Name="MouseOver">
                                        <Storyboard>
                                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="PART_Root">
                                                <EasingDoubleKeyFrame KeyTime="0" Value="2"/>
                                            </DoubleAnimationUsingKeyFrames>
                                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="PART_Root">
                                                <EasingDoubleKeyFrame KeyTime="0" Value="2"/>
                                            </DoubleAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Grid.Resources>
    <Button Content="Button" HorizontalAlignment="Center" VerticalAlignment="Center" Width="75" Style="{StaticResource ButtonStyle1}"/>
</Grid>
Run Code Online (Sandbox Code Playgroud)

虽然Blend使用更通用的变换组,但我们可以看到的主要区别是故事板将元素和通过该元素的属性路径定位到缩放因子.