WPF动画& Datatriggers

时间:2015-09-29 09:28:59

标签: c# wpf animation

我有一个带动画的StackPanel。动画如下所示:

 <DataTrigger Binding="{Binding UseCurrentWindowsUser}" Value="True">
                <DataTrigger.EnterActions>
                    <BeginStoryboard>
                        <Storyboard>
                            <Storyboard>
                                <DoubleAnimation From="80" To="0" Duration="00:00:0.5" Storyboard.TargetProperty="Height">
                                    <DoubleAnimation.EasingFunction>
                                        <BounceEase Bounces="3" EasingMode="EaseOut" Bounciness="5" />
                                    </DoubleAnimation.EasingFunction>
                                </DoubleAnimation>
                            </Storyboard>
                        </Storyboard>
                    </BeginStoryboard>
                </DataTrigger.EnterActions>
                <DataTrigger.ExitActions>
                    <BeginStoryboard>
                        <Storyboard>
                            <Storyboard x:Name="myhideStoryboard">
                                <DoubleAnimation BeginTime="0:0:0.1" From="0" To="80" Duration="00:00:0.5" Storyboard.TargetProperty="Height">
                                    <DoubleAnimation.EasingFunction>
                                        <BounceEase Bounces="3" EasingMode="EaseOut" Bounciness="5" />
                                    </DoubleAnimation.EasingFunction>
                                </DoubleAnimation>
                            </Storyboard>
                        </Storyboard>
                    </BeginStoryboard>
                </DataTrigger.ExitActions>
            </DataTrigger>

当属性UseCurrentWindowsUser为true时,此动画将更改stackpanel的高度。此属性用作绑定CheckBoxIsChecked。我面临的问题是默认情况下此属性应设置为true,因此一旦加载UserControl,动画就会触发。我只希望在用户实际检查或取消选中CheckBox后发生这种情况。我应该使用RoutedEvent吗?有人之前解决了这样的问题吗?

该属性如下所示:

    private bool _useCurrentWindowsUser = true;
    public bool UseCurrentWindowsUser
    {
        get { return _useCurrentWindowsUser; }
        set
        {
            SetProperty(ref _useCurrentWindowsUser, value);
            UserName = value ? WindowsIdentity.GetCurrent()?.Name : string.Empty;
        }
    }

3 个答案:

答案 0 :(得分:1)

这是一个纯粹的XAML解决方案,有点棘手,但相当漂亮。这个想法是你需要另一个触发器来监听相同的属性更改,但动画是在你拥有的实际动画之后启动的。此动画将在确切的持续时间内覆盖其他动画,但随后使用FillBehavior = FillBehavior.Stop停止生效。覆盖触发也完成一次(使用BindingMode.OneTime)。因此,在第一次抑制实际触发器正常工作后,一切都将恢复正常(实际触发器可以正常工作):

将此XAML代码 AFTER 附加到您当前的DataTrigger,以便它会正确覆盖动画:

<DataTrigger Binding="{Binding UseCurrentWindowsUser, Mode=OneTime}" Value="True">
            <DataTrigger.EnterActions>
                <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation From="0" To="0" Duration="00:00:0.5" 
                             Storyboard.TargetProperty="Height" FillBehavior="Stop"/>
                        </Storyboard>
                </BeginStoryboard>
            </DataTrigger.EnterActions>
</DataTrigger>

正如您所看到的,虚假动画只会使Height0的{​​{1}}秒内保持不变。它会产生这样的效果:当0.5最初为UseCurrentWindowsUser时,true会立即设置为Height而不是从0设置为80 ,这在初期很奇怪。

答案 1 :(得分:0)

private bool firstTime = true;
private bool _useCurrentWindowsUser = true;
public bool UseCurrentWindowsUser
{
    get { return _useCurrentWindowsUser; }
    set
    {
        if(!firstTime)
            SetProperty(ref _useCurrentWindowsUser, value);
        firstTime=false;
        UserName = value ? WindowsIdentity.GetCurrent()?.Name : string.Empty;
    }
}

如果你必须第一次设置该属性,创建一个具有相同值的新属性,但没有第一次初始化。

答案 2 :(得分:0)

注册DP时,在propertymetadata中将默认值设置为null / false。这将使您的堆叠面板最初显示高度为80。将其设置为true将在加载时折叠堆栈面板。

public class ViewModel : DependencyObject
    {
        public bool  UseCurrentWindowsUser
        {
            get { return (bool )GetValue(UseCurrentWindowsUserProperty); }
            set { SetValue(UseCurrentWindowsUserProperty, value); }
        }

        // Using a DependencyProperty as the backing store for UseCurrentWindowsUser.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty UseCurrentWindowsUserProperty =
            DependencyProperty.Register("UseCurrentWindowsUser", typeof(bool ), typeof(ViewModel), new PropertyMetadata(null));

    }

将UpdateSourceTrigger设置为Explicit:

<CheckBox x:Name="MyCB" IsChecked="{Binding UseCurrentWindowsUser, UpdateSourceTrigger=Explicit}" Loaded="MyCB_Loaded" Click="MyCB_Click"/>

在其Loaded事件处理程序中将CB检查设置为true,因为您最初希望它为true。

private void MyCB_Loaded(object sender, RoutedEventArgs e)
        {
            MyCB.IsChecked = true;
        }

在CB点击事件处理程序中更新您的来源:

private void MyCB_Click(object sender, RoutedEventArgs e)
    {
        MyCB.GetBindingExpression(CheckBox.IsCheckedProperty).UpdateSource();
    }

现在,您的StackPanel将显示高度为80,您的复选框将被选中。一旦您开始单击复选框,操作即开始。