WPF使用DataTrigger为RenderTransform设置动画

时间:2018-06-11 01:06:44

标签: wpf xaml mvvm

我很难使用数据触发器为Canvas对象的渲染变换设置动画。作为测试用例,我在Canvas上有一个椭圆和两个按钮。当我按下每个按钮时,我希望椭圆的位置为该按钮的X坐标设置动画:

enter image description here

我在这个特定示例中使用按钮的事实既不是在这里也不是在那里,重点是我试图用我的视图模型中绑定到属性的DataTrigger来触发这些动画:

// this is the property my DataTrigger will bind to
private string _Anim;
public string Anim
{
    get { return this._Anim; }
    set
    {
        this._Anim = value;
        RaisePropertyChanged(() => this.Anim);
    }
}

// a command handler for the buttons that sets my animation property
public ICommand AnimCommand { get { return new RelayCommand<string>(OnAnim); } }
private void OnAnim(string value)
{
    this.Anim = String.Empty;   // cancel any existing animation, probably not needed...
    this.Anim = value;
}

这是我用来做这个的Xaml。它基本上只是一个包含椭圆和两个按钮的画布,椭圆有两个故事板,响应后端属性被设置为不同的字符串(即“左”和“右”)而被触发:

<Viewbox xmlns:sys="clr-namespace:System;assembly=mscorlib">
    <Canvas Width="350" Height="150" Background="CornflowerBlue">
        <Ellipse x:Name="MyEllipse" Width="20" Height="20" Fill="Red">
            <Ellipse.RenderTransform>
                <TranslateTransform x:Name="myTransform" X="50" Y="50" />
            </Ellipse.RenderTransform>
            <Ellipse.Style>
                <Style TargetType="Ellipse">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding Anim}" Value="Left">
                            <DataTrigger.EnterActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation Storyboard.TargetProperty="(Ellipse.RenderTransform).(TranslateTransform.X)" To="100" Duration="0:0:1" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </DataTrigger.EnterActions>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding Anim}" Value="Right">
                            <DataTrigger.EnterActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation Storyboard.TargetProperty="(Ellipse.RenderTransform).(TranslateTransform.X)" To="200" Duration="0:0:1" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </DataTrigger.EnterActions>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Ellipse.Style>
        </Ellipse>

        <Button x:Name="btnLeft" Content="Left" Command="{Binding AnimCommand}" CommandParameter="Left" Canvas.Left="100" Canvas.Top="100" Width="32" Height="24" />
        <Button x:Name="btnRight" Content="Right" Command="{Binding AnimCommand}" CommandParameter="Right" Canvas.Left="200" Canvas.Top="100" Width="32" Height="24" />

    </Canvas>
</Viewbox>

当我运行这个时,我可以点击第一个动画,然后点击第二个动画,两次行为都是正确的。但是以相反的顺序单击它们不起作用...“右”按钮动画正确,“左”按钮不起作用。这就好像“正确”的动画仍在运行或锁定属性或其他东西,如果我在Xaml中交换故事板声明的顺序,情况会逆转这一事实进一步支持。

这适用于EventTriggers,我只使用DataTriggers看到它。我也尝试过使用FillBehaviours和HandoffBehaviors,但无济于事。有人可以解释为什么会发生这种情况以及如何解决它?

1 个答案:

答案 0 :(得分:1)

动画完成后,您应删除Storyboard。您可以使用RemoveStoryboard类来执行此操作。只需将BeginStoryboard元素设为Name,然后将RemoveStoryboard元素添加到ExitActions的{​​{1}}:

DataTrigger

其他选项会将<Style TargetType="Ellipse"> <Style.Triggers> <DataTrigger Binding="{Binding Anim}" Value="Left"> <DataTrigger.EnterActions> <BeginStoryboard Name="sb"> <Storyboard> <DoubleAnimation Storyboard.TargetProperty="(Ellipse.RenderTransform).(TranslateTransform.X)" To="100" Duration="0:0:1" /> </Storyboard> </BeginStoryboard> </DataTrigger.EnterActions> <DataTrigger.ExitActions> <RemoveStoryboard BeginStoryboardName="sb" /> </DataTrigger.ExitActions> </DataTrigger> <DataTrigger Binding="{Binding Anim}" Value="Right"> <DataTrigger.EnterActions> <BeginStoryboard Name="sb2"> <Storyboard> <DoubleAnimation Storyboard.TargetProperty="(Ellipse.RenderTransform).(TranslateTransform.X)" To="200" Duration="0:0:1" /> </Storyboard> </BeginStoryboard> </DataTrigger.EnterActions> <DataTrigger.ExitActions> <RemoveStoryboard BeginStoryboardName="sb2" /> </DataTrigger.ExitActions> </DataTrigger> </Style.Triggers> </Style> 的{​​{1}}设置为FillBehavior,但动画完成后,Storyboard的位置将会恢复。

  

我不敢工作。单击“向左”,“向右”首先工作,但再次单击“左”会导致动画从位置0重新开始,即使我设置了HandoffBehaviors和FillBehaviours。

摆脱XAML中的Stop,然后编写一些自定义代码。这有效:

Ellipse

<强> XAML:

DataTriggers