gpt4 book ai didi

c# - 消除代码隐藏中的 Storyboard Completed 处理程序

转载 作者:太空宇宙 更新时间:2023-11-03 10:58:44 26 4
gpt4 key购买 nike

一点背景:

我正在构建一个窗口,我有一个 Storyboard ,用于在完成用户启动的任务时简要显示一个弹出窗口,而无需用户确认。它看起来像这样:

<UserControl.Resources>
<Storyboard x:Name="FadingFeedback" x:Key="FadingFeedback" Completed="FadingFeedback_Completed">
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
From="0.5"
To="0"
BeginTime="0:0:0"
Duration="0:0:2.0">
<DoubleAnimation.EasingFunction>
<ExponentialEase Exponent="10" EasingMode="EaseIn" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</UserControl.Resources>

我使用的弹出窗口是这样定义的:

<Popup Name="popup" Placement="Center" PopupAnimation="Fade" AllowsTransparency="True"
IsOpen="{Binding DoShowMessage}">
<Popup.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding DoShowMessage}" Value="true">
<Setter Property="Popup.IsOpen" Value="true" />
<DataTrigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource FadingFeedback}" />
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Popup.Style>
<Border Background="Black" BorderBrush="White" BorderThickness="1" CornerRadius="5">
<Grid Background="Transparent">
<Grid Name="popupGrid" Background="Black" Grid.Column="0" Grid.Row="0" />
<Label Name="popupLabel" HorizontalAlignment="Center" Foreground="White"
VerticalAlignment="Center"
Background="Transparent"
Grid.Column="0"
Grid.Row="0"
FontSize="16"
Content="{Binding TextMessage}"/>
</Grid>
</Border>
</Popup>

有一个 ViewModel 是它的数据上下文,它有几个属性(在绑定(bind)中引用)来提供 TextMessage 字符串和 DoShowMessage bool。它们的定义如下:

    private string _textMessage;
public string TextMessage
{
get { return _textMessage; }
set
{
_textMessage = value;
OnPropertyChanged("TextMessage");
}
}

private bool _doShowMessage;
public bool DoShowMessage
{
get { return _doShowMessage; }
set
{
_doShowMessage = value;
OnPropertyChanged("DoShowMessage");
}
}

在适当的时候,ViewModel 将设置 DoShowMessage 属性,XAML 中的绑定(bind)将显示弹出窗口并开始 Storyboard。

现在,我在弹出窗口的代码后面有 Completed 处理程序,它就是这样做的:

    void StatusFader_Completed(object sender, EventArgs e)
{
popup.IsOpen = false;
}

这很好用,因为 popup.IsOpen 绑定(bind)到 ViewModel DoShowMessage 的底层属性,它将重置该 bool 值。

我的问题:

Storyboard完成后,是否有“更好”的方法来处理 DoShowMessage 属性的重置?或者换句话说,有没有办法在 XAML 本身中做到这一点?我读过这样一种观点/惯例,即后面的代码应该(大部分)没有 View 代码,但似乎(至少对我而言)这(事件处理程序)是一种合理的方法。想知道在 XAML 中是否有办法做到这一点。

最佳答案

是的,当然你可以用另一种方式来做。通过 ObjectAnimationUsingKeyFrames 设置 popup.IsOpen="False"

例如:

Storyboard

<Storyboard x:Name="FadingFeedback" x:Key="FadingFeedback"> 
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="0.5"
To="0" BeginTime="0:0:0" Duration="0:0:2.0">

<DoubleAnimation.EasingFunction>
<ExponentialEase Exponent="10" EasingMode="EaseIn" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>

<ObjectAnimationUsingKeyFrames BeginTime="0:0:2.0" Storyboard.TargetProperty="(Popup.IsOpen)">
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<sys:Boolean>False</sys:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>

<Popup Name="popup" Placement="Center" PopupAnimation="Fade" AllowsTransparency="True" IsOpen="{Binding DoShowMessage}">
<Popup.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding DoShowMessage}" Value="True">
<!--<Setter Property="Popup.IsOpen" Value="True" />--> <!-- not necessarily, because we have Popup.IsOpen = True -->

<DataTrigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource FadingFeedback}" />
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Popup.Style>
...
</Popup>

但是在这种情况下,在动画之外打开Popup是有问题的,因为动画的属性是第一位的,但是其他来源,比如代码,指定不会。引自 MSDN :

In order to have any practical effect, an animation of a property must be able to have precedence over the base (unanimated) value, even if that value was set locally.

这样可以通过代码访问,从属性中删除动画,从而允许访问属性,如下所示:

XAML

<Grid>
<Grid.Triggers>
<EventTrigger SourceName="CloseButton" RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="MyPopup"
Storyboard.TargetProperty="(Popup.IsOpen)"
Duration="0:0:0">

<DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="False" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>

<Popup x:Name="MyPopup" Width="200" Height="200" IsOpen="True">
<Grid Background="Azure">
<Label Content="Test label" />
</Grid>
</Popup>

<Button Name="OpenButton" Content="OpenButtonFromCode" Width="140" Height="30" Click="OpenButton_Click" />
<Button Name="CloseButton" Content="CloseButtonfromEventTrigger" Width="180" Height="30" Margin="0,80,0,0" />
</Grid>

代码隐藏

private void OpenButton_Click(object sender, RoutedEventArgs e)
{
MyPopup.BeginAnimation(Popup.IsOpenProperty, null);
MyPopup.IsOpen = true;
}

有一个选择,或者干脆在Storyboard_Completed事件中把Falsepopup.IsOpen丢进去,或者做动画,但要访问代码,必须将其删除。

对于我自己,我通常这样做,创建一个附加的依赖属性( bool 值),将触发动画绑定(bind)到这个属性。如果它的值为 true,则启动动画,但它将重新运行,在 Storyboard_Completed 事件中我不得不将属性折叠为 false。就我个人而言,这是一种更简单的方法。

关于c# - 消除代码隐藏中的 Storyboard Completed 处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18492448/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com