WPF MVVM属性更改动画

时间:2009-10-30 13:31:59

标签: wpf animation mvvm

我正在寻找一种干净的方式来启动具有动态值的动画。基本上我想做一个动画,其中一个元素根据另一个元素的数据改变宽度。假设我有一个文本属性为绑定的TextBlock。当这个属性改变时,我想要一个可视元素说一个Rectangle,以便我们做一个DoubleAnimation,将宽度从之前的值改为新值。

如果可能的话,我正试图远离将代码放入我的视图中。我已经研究过DataTriggers,但它们似乎要求你知道它的价值,例如Enum。在我的情况下,只是需要触发故事板的值更改,动画需要从当前(上一个)值开始,并很好地移动到新值。

任何想法。也许我只是错过了一处房产。

4 个答案:

答案 0 :(得分:15)

这是我最终解决的问题。要根据我的ViewModel中的数据执行动画,我使用了DataTrigger。以下是我的控制风格。

<Style TargetType="Grid" x:Key="DetailRotation" >
    <Style.Triggers>
        <DataTrigger Binding="{Binding Path=AnimationState}" Value="New">
            <DataTrigger.EnterActions>
                <StopStoryboard BeginStoryboardName="EndAnimation" />
                <BeginStoryboard Name="NewAnimation">
                    <Storyboard>
                        <ThicknessAnimation Storyboard.TargetProperty="Margin" From="0,30,0,0" To="0,0,0,0" Duration="0:0:1" />
                        <DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:1" />
                    </Storyboard>
                </BeginStoryboard>
            </DataTrigger.EnterActions>
            <DataTrigger.ExitActions>

            </DataTrigger.ExitActions>

        </DataTrigger>
        <DataTrigger Binding="{Binding Path=AnimationState}" Value="End">
            <DataTrigger.EnterActions>
                <StopStoryboard BeginStoryboardName="NewAnimation" />
                <BeginStoryboard Name="EndAnimation">
                    <Storyboard>
                        <ThicknessAnimation Storyboard.TargetProperty="Margin" From="0,0,0,0" To="0,-20,0,0" Duration="0:0:1"/>
                        <DoubleAnimation Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="0:0:1" />
                    </Storyboard>
                </BeginStoryboard>
            </DataTrigger.EnterActions>
        </DataTrigger>

    </Style.Triggers>
</Style>

答案 1 :(得分:1)

您可以使用Attached Properties探索将所需逻辑连接到您想要的故事板/动画。

这不一定会阻止您编写代码,但它会将其与视图分开,并允许它在多个视图中重复使用。

答案 2 :(得分:0)

由于动画修改的属性无法在动画“上下文”之外设置,我想出了一个代码解决方案,因为我无法在XAML中有效地执行相同的操作。

private void UserControl_IsVisibleChanged(object sender, 
    DependencyPropertyChangedEventArgs e)
{
    if (this.Visibility == Visibility.Visible)
    {
        DoubleAnimation fadeIn = new DoubleAnimation();
        fadeIn.From = 1d;
        fadeIn.To = 1d;
        fadeIn.Duration = new Duration(new TimeSpan(0, 0, 0));

        DoubleAnimation fade = new DoubleAnimation();
        fade.From = 1d;
        fade.To = 0d;
        fade.BeginTime = TimeSpan.FromSeconds(5);
        fade.Duration = new Duration(new TimeSpan(0, 0, 1));

        NameScope.SetNameScope(this, new NameScope());
        this.RegisterName(this.Name, this);

        Storyboard.SetTargetName(fadeIn, this.Name);
        Storyboard.SetTargetProperty(fadeIn, new PropertyPath
            (UIElement.OpacityProperty));

        Storyboard.SetTargetName(fade, this.Name);
        Storyboard.SetTargetProperty(fade, new PropertyPath
            (UIElement.OpacityProperty));

        Storyboard sb = new Storyboard();
        sb.Children.Add(fadeIn);
        sb.Children.Add(fade);

        sb.Completed += new EventHandler(sb_Completed);
        sb.Begin(this);
    }
}

void sb_Completed(object sender, EventArgs e)
{
    this.Visibility = Visibility.Hidden;
}

答案 3 :(得分:0)

实际上,您希望将DoubleAnimation.ToProperty绑定到ViewModel属性并为实际控件设置动画。问题是在ToProperty更改时应继续动画。我的解决方案将所有这些逻辑封装到包含MarkupExtenstion的{​​{1}}。

Binding

您可以对其他动画类执行相同的操作以设置其他类型的动画。