我有一个带动画的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的高度。此属性用作绑定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;
}
}
答案 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>
正如您所看到的,虚假动画只会使Height
在0
的{{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,您的复选框将被选中。一旦您开始单击复选框,操作即开始。