一个简单的需求:当程序发生异常时候,在界面上动画显示异常信息。

这个需求看似简单,只需要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模式下,完成了动画的触发。

WPF 在MVVM模式下应用动画的更多相关文章

  1. 笔记03 wpf 在MVVM模式下怎样在Viewmodel里面获得view的控件对象

     转自http://blog.csdn.net/qing2005/article/details/6601199http://blog.csdn.net/qing2005/article/detail ...

  2. WPF中MVVM模式下控件自有的事件绑定

    1.原因 在WPF中单纯的命令绑定往往不能满足覆盖所有的事件,例如ComboBox的SelectionChanged事件,DataGrid的SelectionChanged事件等等,这时就可以用事件绑 ...

  3. WPF:MVVM模式下ViewModel关闭View

    不外乎两种基本方法. 消息通知和参数传递. 一.消息通知 利用View里的IsEnable属性 原理是这样的: 1.UI中的IsEnabled绑定VM中的属性 2.UI的后台代码中,注册IsEnabl ...

  4. WPF 在MVVM模式下弹出子窗体的方式

    主要是通过一个WindowManager管理类,在window后台代码中通过WindowManager注册需要弹出的窗体类型,在ViewModel通过WindowManager的Show方法,显示出来 ...

  5. WPF:MVVM模式下ViewModel调用View

    两种基本方法: 消息通知和参数传递 一.消息通知 利用View里的IsEnable属性 原理是这样的: 1.UI中的IsEnabled绑定VM中的属性 2.UI的后台代码中,注册IsEnableCha ...

  6. WPF中在MVVM模式下,后台绑定ListCollectionView事件触发问题

    问题:WPF中MVVM模式下 ListView绑定ListCollectionView时,CurrentChanged无法触发 解决方案: 初期方案:利用ListView的SelectionChang ...

  7. WPF实战案例-MVVM模式下在Xaml中弹出窗体

    相信很多学习和开发wpf项目的同学都了解过mvvm模式,同样,在mvvm模式下会有一个不可忽视的问题,就是怎么在xaml中弹出窗体,而不破坏MVVM本身的结构. 关于弹出窗体的方式还是很多的,本文先讲 ...

  8. MVVM模式下WPF动态绑定展示图片

    MVVM模式下WPF动态展示图片,界面选择图标,复制到项目中固定目录下面,保存到数据库的是相对路径,再次读取的时候是根据数据库的相对路径去获取项目中绝对路径的图片展示. 首先在ViewModel中 / ...

  9. wpf mvvm模式下CommandParameter传递多参

    原文:wpf mvvm模式下CommandParameter传递多参 CommandParameter一般只允许设置一次,所以如果要传递多参数,就要稍微处理一下.我暂时还没找到更好的方案,下面介绍的这 ...

  10. WPF MVVM模式下ComboBox级联效果 选择第一项

    MVVM模式下做的省市区的级联效果.通过改变ComboBox执行命令改变市,区. 解决主要问题就是默认选中第一项 1.首先要定义一个属性,继承自INotifyPropertyChanged接口.我这里 ...

随机推荐

  1. 用Linux命令操作mysql数据库

    操作mysql数据库,相信大家最熟悉的应该是用navicat工具来新建数据库,建表,查询数据,查看表结构等. 但是如果数据库与本操作机器不在同一个局域网内,并且对方环境也不支持vpn的情况下,如何查询 ...

  2. 计算机网络 vlan

    目录 一.vlan的概念 二.vlan的优势 三.vlan的种类 四.静态vlan的配置 五.trunk的概念和配值 六.实验 一.vlan的概念 在传统的以太网中,所有的用户都是同一个广播域,当数据 ...

  3. js 字符串格式数组转为数组对象

    工作中经常会遇到将json字符串转换为json对象,但是将字符串格式数组转为数组对象的场景却不多 如: 其中label_exp: "["cap_pop","wk ...

  4. web自动化06-键盘操作

    键盘操作 1.说明: 1). 模拟键盘上一些按键或者组合键的输入 如:Ctrl+C .Ctrl+V: 2). Selenium中把键盘的按键都封装在Keys类中 2. Keys类 导包:from se ...

  5. Vue——动态组件、插槽、Vue-cli创建项目、Vue项目目录结构、编写规范、es6导入导出语法

    动态组件 // <component :is="who"></component> // component标签的is属性等于组件名字,这里就会显示这个组件 ...

  6. gitlab docker升级报错

    背景 使用docker部署gitlab(9.5.4)后,发现合并代码有问题 日志: 看gitlab官网此问题已修复,由于上传了一批代码,又懒得重建,决定对gitlab升级 docker启动命令: do ...

  7. 用声明式宏解析 Rust 语法之 enum parser

    上一篇用声明式宏解析 Rust 语法 我们的 "macro parser" 解析了 function 和 struct, 这篇来尝试 parse 一下更复杂的 enum 为什么说 ...

  8. spark连接mysql数据库

    1.安装启动检查Mysql服务.netstat -tunlp (3306) 2.spark 连接mysql驱动程序. –cp /usr/local/hive/lib/mysql-connector-j ...

  9. 【python基础】类-初识类

    1.面向对象思想 在认识类之前,我们需要理解面向对象思想和面向过程思想. 面向过程思想:要拥有一间房屋,面向过程像是自己来修盖房屋,如果需要经过选址.购买材料.砌墙.装修等步骤,面向过程编程,就相当于 ...

  10. 如何取消Blazor Server烦人的重新连接?

    如何取消Blazor Server烦人的重新连接? 相信很多Blazor的用户在开发内部系统上基本上都选择速度更快,加载更快的Blazor Server模式. 但是Blazor Server由于是Si ...