一个简单的需求:当程序发生异常时候,在界面上动画显示异常信息。
这个需求看似简单,只需要try……catch到异常,然后把异常的信息写入界面就OK了。
但在MVVM时,就不是这么简单了。MVVM模式下,追求前后端的分离。然后catch到的异常,也只能在后台代码中。如果传递到前台呢?
这自然就想到了Binding。在ViewModel中定义一个属性接收异常信息。然后在xaml中去绑定这个属性,就可以显示它了。
如下代码所示:
C#:
Xaml:
<TextBlock Text="{Binding Exception}"/>
C#代码:
/// <summary> /// 数据类 /// </summary> public class BTN:NotifyObject { public string Exception { get => exception; set { exception = value; OnPropertyChanged(); } } string exception = string.Empty; }
如此一来,只需要给Exception属性赋值,TextBlock就能显示了。
OK,基本需求搞定。当如何使用动画呢?
首先,实现这种动画有三种方式:
1. 改变TextBlock的Visibility属性,从Hidden 到 Visible。这中方式会用到KeyFrameAnimation。
2. 改变TextBlock的Height属性,从0 到40(或者30),它就会有个“长高”的过程。
3. 改变TextBlock的Opacity属性,从0到1,它就会有个慢慢显现的过程。
这里推荐使用第2或者第3中。因为它们使用的都是DoubleAnimation对象,比第一种使用KeyFrameAnimation对象要简单许多。
其次,如何触发动画呢?
在传统的编程模式下,只要在给Exception属性赋值时,控制TextBlock去显示动画就搞定了。但现在实在MVVM模式下!后台拿不到前台元素!
此时,触发器就发挥作用了。即,当某一个属性的值为特定值时,执行某些动作。
如果使用TextBlock的Text属性作为触发器,在Xaml中Value值不好写(因为在Xaml中,唯一能确定的string类型的值是Null或者String.Empty)。
因此这里可以为TextBlock添加一个附件属性,让它去绑定一个值。当这个属性的值满足条件的时候,就触发动画。
看代码吧:
/// <summary> /// 数据类 /// </summary> public class BTN:NotifyObject { public string Exception { get => exception; set { exception = value; OnPropertyChanged(); HasException = !string.IsNullOrWhiteSpace(value); } } string exception = string.Empty; // 添加HasException属性,用于前台附加属性的绑定 public bool HasException { get=>hasException; set { hasException = value; OnPropertyChanged(); } } bool hasException = false; }
public class NotifyUI {
// 定义附加属性,用于控件去绑定后台属性 private static readonly DependencyProperty HasMessageProperty = DependencyProperty.RegisterAttached( "HasMessage", typeof(bool),typeof(NotifyUI),new PropertyMetadata(false)); public static void SetHasMessage(DependencyObject element, bool value) => element.SetValue(HasMessageProperty, value); public static bool GetHasMessage(DependencyObject element) => (bool)element.GetValue(HasMessageProperty); }
<TextBlock VerticalAlignment="Bottom" Background="Yellow" Height="0" Text="{Binding Exception}" local:NotifyUI.HasMessage="{Binding HasException}"> <!-- 使用附加属性去绑定后台的HasException属性 --> <TextBlock.Style> <Style TargetType="TextBlock"> <Style.Triggers>
<!-- 设置触发器。当附加属性的值为True时,开始动画 --> <Trigger Property="local:NotifyUI.HasMessage" Value="True"> <Trigger.EnterActions> <BeginStoryboard> <Storyboard>
<!-- 希望动画播放完毕后的,暂定一段时间,然后自动消退。这里不使用AutoReverse = True,因为在消退前不会暂定。--> <DoubleAnimation To="40" Duration="0:0:0.2" Storyboard.TargetProperty="Height"> <DoubleAnimation.EasingFunction> <BounceEase EasingMode="EaseIn"/> </DoubleAnimation.EasingFunction> </DoubleAnimation>
<!-- 设置BeignTime,是在第一个动画播放完之后,与第二个动画开始播放之间有时间间隔 --> <DoubleAnimation To="0" Duration="0:0:0.2" Storyboard.TargetProperty="Height" BeginTime="0:0:1.2"> <DoubleAnimation.EasingFunction> <BounceEase EasingMode="EaseOut"/> </DoubleAnimation.EasingFunction> </DoubleAnimation> </Storyboard> </BeginStoryboard> </Trigger.EnterActions> </Trigger> </Style.Triggers> </Style> </TextBlock.Style> </TextBlock>
如此,就通过两个属性,在MVVM模式下,完成了动画的触发。
标签:动画,string,MVVM,TextBlock,WPF,public,属性 From: https://www.cnblogs.com/raynado/p/17529478.html