故事板未触发的数据触发

时间:2019-08-28 07:51:46

标签: c# wpf storyboard datatrigger

我在同一张Image上有5个不同的DataTriggers,每个用于相同的Binding,但具有不同的Value,它们分别将Image旋转一个不同的角度。 每次更改值后,该值都将重置为0。

当我没有添加DataTrigger.ExitActions> <RemoveStoryboard>东西时,它们只工作了一次,但是只工作了一次,因此,如果steps绑定再次获得该值,它们将不会触发。

<Image x:Name="drehteller" HorizontalAlignment="Center" VerticalAlignment="Center" RenderTransformOrigin="0.5,0.5" Source="{Binding drehteller_image}">
        <Image.RenderTransform>
            <RotateTransform/>
        </Image.RenderTransform>
        <Image.Style>
            <Style>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding steps}" Value="1">
                        <DataTrigger.EnterActions>
                            <BeginStoryboard x:Name="Storyboard1Step">
                                <Storyboard>
                                    <DoubleAnimation
                                        Storyboard.TargetProperty="RenderTransform.Angle" 
                                        By="72"
                                        Duration="00:00:00:03"
                                    />
                                </Storyboard>
                            </BeginStoryboard>
                        </DataTrigger.EnterActions>
                        <DataTrigger.ExitActions>
                            <RemoveStoryboard BeginStoryboardName="Storyboard1Step"/>
                        </DataTrigger.ExitActions>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding steps}" Value="2">
                        <DataTrigger.EnterActions>
                            <BeginStoryboard x:Name="Storyboard2Step">
                                <Storyboard>
                                    <DoubleAnimation
                                        Storyboard.TargetProperty="RenderTransform.Angle" 
                                        By="144"
                                        Duration="00:00:00:03"
                                    />
                                </Storyboard>
                            </BeginStoryboard>
                        </DataTrigger.EnterActions>
                        <DataTrigger.ExitActions>
                            <RemoveStoryboard BeginStoryboardName="Storyboard2Step"/>
                        </DataTrigger.ExitActions>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding steps}" Value="3">
                        <DataTrigger.EnterActions>
                            <BeginStoryboard x:Name="Storyboard3Step">
                                <Storyboard>
                                    <DoubleAnimation
                                        Storyboard.TargetProperty="RenderTransform.Angle" 
                                        By="216"
                                        Duration="00:00:00:03"
                                    />
                                </Storyboard>
                            </BeginStoryboard>
                        </DataTrigger.EnterActions>
                        <DataTrigger.ExitActions>
                            <RemoveStoryboard BeginStoryboardName="Storyboard3Step"/>
                        </DataTrigger.ExitActions>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding steps}" Value="4">
                        <DataTrigger.EnterActions>
                            <BeginStoryboard x:Name="Storyboard4Step">
                                <Storyboard>
                                    <DoubleAnimation
                                        Storyboard.TargetProperty="RenderTransform.Angle" 
                                        By="72"
                                        Duration="00:00:00:03"
                                    />
                                </Storyboard>
                            </BeginStoryboard>
                        </DataTrigger.EnterActions>
                        <DataTrigger.ExitActions>
                            <RemoveStoryboard BeginStoryboardName="Storyboard4Step"/>
                        </DataTrigger.ExitActions>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding steps}" Value="5">
                        <DataTrigger.EnterActions>
                            <BeginStoryboard x:Name="Storyboard5Step">
                                <Storyboard>
                                    <DoubleAnimation
                                        Storyboard.TargetProperty="RenderTransform.Angle" 
                                        By="360"
                                        Duration="00:00:00:03"
                                    />
                                </Storyboard>
                            </BeginStoryboard>
                        </DataTrigger.EnterActions>
                        <DataTrigger.ExitActions>
                            <RemoveStoryboard BeginStoryboardName="Storyboard5Step"/>
                        </DataTrigger.ExitActions>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Image.Style>
    </Image>

也许有人对我做错了什么有个想法,我认为RemoveStoryboard可能会解决他们只会解雇一个但看起来却没有解雇的问题。

编辑:发现没有ExitActions的情况下,我可以随意触发值1的触发器,只要该值永远不会高于1,所以如果我一次触发值2的触发器,值为1的触发器不再起作用,如果我触发值为3的触发器,则值为2的触发器不再起作用。依此类推,猜想你明白了。

2 个答案:

答案 0 :(得分:2)

一个非常简单而直接的解决方案是在后面的代码中运行动画:

// Solution
nextStep = () => {
  const { items } = this.state;

  if (items.length === 1) {
    this.setState({ isActive: false });
    return;
  }

  const newItems = [...items];
  newItems.pop();
  this.setState(prevState => ({ items: newItems, step: prevState.step + 1 }));
};

// Old code with issues
nextStep = () => {
  const { step } = this.state;
  if (step === Items.length - 1) {
    this.setState({ isActive: false, step: 0, item: Items[0] });
    return;
  }

  this.setState(prevState => ({
    step: prevState.step + 1,
    item: Items[prevState.step + 1]
  }));
};

这与MVVM并不矛盾,因为视图模型仍然对视图一无所知。这是纯粹的观点方面。

答案 1 :(得分:1)

您也可以使用attached behavior进行此操作。这些是可重用的视图逻辑,您可以将这些逻辑附加到各种UI元素上,而无需将其放在后面的代码中。

您将需要Microsoft.Xaml.Behaviors.Wpf NuGet package(该文件曾经作为Visual Studio的“ Blend for Visual Studio SDK for .NET”组件分发,但在VS 2019中已更改)。

定义您的行为。请注意,AssociatedObject指的是与此行为相关联的Image,请参见下文。

public class AnimateBehavior : Behavior<Image>
{
    public int Steps
    {
        get => (int)GetValue(StepsProperty);
        set => SetValue(StepsProperty, value);
    }
    public static readonly DependencyProperty StepsProperty =
        DependencyProperty.Register(nameof(Steps), typeof(int), typeof(AnimateBehavior), new PropertyMetadata(0, (d, e) => ((AnimateBehavior)d).StepsChanged(e)));

    private void StepsChanged(DependencyPropertyChangedEventArgs e)
    {
        if (AssociatedObject == null)
            return;

        AssociatedObject.RenderTransform.BeginAnimation(
            RotateTransform.AngleProperty,
            new DoubleAnimation()
            {
                By = (int)e.NewValue * 72,
                Duration = TimeSpan.FromSeconds(3),
            });
    }
}

然后在您的XAML中,需要以下名称空间:

xmlns:behaviors="http://schemas.microsoft.com/xaml/behaviors"

然后:

<Image ...>
    <Image.RenderTransform>
        <RotateTransform/>
    </Image.RenderTransform>
    <behaviors:Interaction.Behaviors>
        <local:AnimateBehavior Steps="{Binding steps}"/>
    </behaviors:Interaction.Behaviors>
</Image>