[译]WPF MVVM 架构 Step By Step(5)(添加actions和INotifyPropertyChanged接口)
应用不只是包含textboxs和labels,还包含actions,如按钮和鼠标事件等。接下来我们加上一些像按钮这样的UI元素来看MVVM类怎么演变的。与之前的UI相比,这次我们加上一个"Cal Tax"按钮,当我们点击这个依赖于“sales amount”的按钮时,它会计算税费并显示在同窗口内。
为了完成所述的功能,我们先在Model类中添加一个CalculateTax的方法。当这个方法被调用时,它根据工资范围来计算税费并把它储存在Tax这个属性中。
public class Customer { ... private double _Tax; public double Tax => _Tax; public void CalculateTax() { if (Amount > 2000) { _Tax = 20; } else if (Amount > 1000) { _Tax = 10; } else { _Tax = 5; } } }
因为view model是model类的包装,我们需要在view model中创建一个方法来调用model的Calculate方法。
public void Calculate() {
.... obj.CalculateTax(); }
现在我们希望从界面上调用Calculate方法时使用XAML而不是后台代码。现在还不能在XAML中直接调用Calculate方法,这时我们需要用到WPF command类。
如果你想用属性来传递数据到view model 我们需要用到bindings,如果你想要从view传递actions我们需要用到commands.
所有属于view的actions都被传递到command类,因此第一步就是创建command类。为了创建一个这样的command类我们需要像下面这样实现ICommand接口。
有2个方法我们必须要实现,CanExecute和Execute。在Execute方法中,我们写当这个action发生时我们真的要执行的逻辑。在CanExecute方法中,我们写一些验证代码来确定我们的Execute方法是否应该被执行。
public class ButtonCommand:ICommand { public bool CanExecute(object parameter) { //验证代码 } public void Execute(object parameter) { //执行逻辑 } public event EventHandler CanExecuteChanged; }
现在所有的actions调用时先来到command类然后再路由到view model 类。换句话说就是command类需要覆盖view model类。
下面是一些简短的代码摘要。有4个重要的点需要记下来:
- 创建的view model对象是私有成员级别的对象。
- 这个对象将view model通过构造函数来传递。
- 暂时我们没有在CanExecute中添加验证代码,它永远返回true.
- 在Execute方法中我们调用了view model类的Calculate方法。
public class ButtonCommand:ICommand { private CustomerViewModel _obj; public ButtonCommand(CustomerViewModel obj) { _obj = obj; } public bool CanExecute(object parameter) { //验证代码 return true; } public void Execute(object parameter) { //执行逻辑 _obj.Calculate(); } public event EventHandler CanExecuteChanged; }
在上面的command的代码中,view model对象通过构造函数来传递。因此view model类需要创建一个command对象并通过ICommand接口暴露这个command对象。这个ICommand接口会被利用然后在WPF XAML中调用。一些关于CustomerViewModel类去用command类的重点:
- command类是CustomerViewModel类的一个私有成员级别的对象。
- 在view model类中,当前实例通过构造函数传递给command类。当我们之前解释command类代码时,我们说command类的构造函数获取到view model类的实例。因此在这一节中,我们把当前实例传递给command类。
- command对象以ICommand接口的形式暴露出来,这样它就可以在XAML里面来用了。
public class CustomerViewModel { private readonly ButtonCommand _objButtonCommandCommand; public CustomerViewModel() { _objButtonCommandCommand=new ButtonCommand(this); } public ICommand CalClick => _objButtonCommandCommand;
..... }
在UI上添加一个按钮来让它把按钮的行为和暴露为ICommand的方法关联起来。现在可以打开这个按钮的属性,找到命令属性,然后点击创建数据绑定。
然后选择static resource然后给按钮加上ButtonCommand。
当你去点击cal tax的按钮时,它回去执行CalculateTax方法并把tax的值存在_tax变量中。
换句话中,UI不会自动的被通知关于Tax Cal.因此我们需要传递从对象到UI的某种通知告诉它们tax值已经改变了,然后UI来重新加载新的绑定的数据。
在View model 勒种,我们需要发送一个通知时间到view上。
要在VIEW MODEL类中使用通知我们需要做3件事情。所有的3件事情在下面都标出来了。
- 像如下代码一样实现INotifyPropertyChanged接口。一旦你实现了这个接口,它就创建了一个PropertyChangedEventHandler的事件对象。
- 在Calculate方法中用PropertyChanged对象来引发事件,并且在这里面表示哪个属性会被通知。例子中使用的是Tax属性。为了安全起见我们在使用PropertyChanged对象之前先检查它是否为空。
public class CustomerViewModel:INotifyPropertyChanged {
....
public void Calculate() { obj.CalculateTax(); OnPropertyChanged(nameof(Tax)); } public event PropertyChangedEventHandler PropertyChanged; [NotifyPropertyChangedInvocator] protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
当你运行这个应用时,你应该可以看到当你点击按钮时Tax的值也发生了变化。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
WPF MVVM 架构 Step By Step(3)(把后台代码移到一个类中)
原文: WPF MVVM 架构 Step By Step(3)(把后台代码移到一个类中) 我觉得大部分开发者应该已经知道怎么去解决这个问题。一般都是把后台代码(GLUE code)移动到一个类库。这个类库用来代表UI的属性和行为。任何代码当被移到一个类库中时都可以被编译成一个DLL,然后可以在任何类型的.net项目中去引用它。所以接下来我们来创建一个非常简单的MVVM的例子在之后我们会升级我们的例子让他成为一个专业的MVVM例子。 我们首先创建一个"CustomerViewModel"的类来包含所有的“GLUE code”.CustomerViewModel类用来表示你的UI,因此我们应该保持这个类中属性与UI的命名规则同步。在下图我们可以看到CustomerViewModel类有像TxtCustomerName映射到CustomerName这样的属性,TxtAmount映射到Amount等等。 下面是这个类中的具体代码: public class CustomerViewModel { private Customer obj = new Customer(); public st...
- 下一篇
WPF MVVM 架构 Step By Step(6)(把actions从view model解耦)
原文: WPF MVVM 架构 Step By Step(6)(把actions从view model解耦) 到现在为止,我们创建了一个简单的MVVM的例子,包含了实现了的属性和命令。我们现在有这样一个包含了例如textbox类似的输入元素的视图,textbox用绑定来和view model联系,像点击button这样的行为用命令来联系。view model和model在内部通信。 但是在上面的架构中有一个问题,command类和view model有很严重的耦合。如果你记得command类的代码(在下面也有展示),在构造函数中传递view model对象,意味着这个command 类不能再其他的view model中重用。 public class ButtonCommand:ICommand { private CustomerViewModel _obj; public ButtonCommand(CustomerViewModel obj) { _obj = obj; } ...... ...... } 但是我们现在思考下什么是一个行为。它是一个来自于最终用户的像鼠标点击,按钮...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS6,CentOS7官方镜像安装Oracle11G
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Hadoop3单机部署,实现最简伪集群
- MySQL8.0.19开启GTID主从同步CentOS8