WPF动画&;数据触发器

本文关键字:数据 触发器 amp 动画 WPF | 更新日期: 2023-09-27 18:15:06

我有一个带有动画的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时,此动画将更改堆叠面板的高度。此属性用作到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;
        }
    }

WPF动画&;数据触发器

这里有一个纯XAML解决方案,它有点棘手,但相当漂亮。这个想法是,您需要另一个触发器来侦听相同的属性更改,但动画是在实际动画之后启动的。此动画将覆盖精确持续时间内的其他动画,但随后使用FillBehavior = FillBehavior.Stop停止效果。超控触发也会执行一次(通过使用BindingMode.OneTime(。因此,在第一次抑制实际触发器正常工作后,一切都将再次正常(然后实际触发器可以正常工作(:

将此XAML代码附加到当前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>

正如您所看到的,假动画只是在0.5秒的相同持续时间内将Height保持在0不变。这样做的效果是,当UseCurrentWindowsUser最初是true时,Height立即设置为0,而不是从80动画化为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;
    }
}

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

注册DP时,在属性数据中将默认值设置为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 checked设置为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的高度出现,您的复选框将被选中。一旦您开始单击复选框,操作就会开始。