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时,此动画将更改堆叠面板的高度。此属性用作到CheckBox
、IsChecked
的绑定。我面临的问题是,该属性默认情况下应设置为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;
}
}
这里有一个纯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的高度出现,您的复选框将被选中。一旦您开始单击复选框,操作就会开始。