简单的介绍下WPF中的MVVM框架

最近在研究学习Swift,苹果希望它迅速取代复杂的Objective-C开发,引发了一大堆热潮去学它,放眼望去各个培训机构都已打着Swift开发0基础快速上手的招牌了。不过我觉得,等同于无C++基础上手学习C#一样,即使将来OC被淘汰,那也是N年之后的事情,如果真的要做IOS开发,趁现在Swift才刚开始,花那么几个月去了解一下OC绝对是一件有帮助的事情。

扯远了,我前几天刚接触到一个叫做mvvm的框架,发现很有意思,带着学习的态度来写点东西,不足之处一起研究。还有一个很重要的原因,我发现不少同学学习WPF的时候的思维和Windows Form是完全一样的,也就是说为什么用WPF而不用WinForm对于他们来说仅仅是:WPF的UI好看!

下面是WPF的一个简介:

Windows Presentation Foundation(WPF)是美国微软公司推出.NET Framework 3.0及以后版本的组成部分之一,它是一套基于XML.NET Framework矢量绘图技术的展示层开发框架,微软视其为下一代用户界面技术。

WPF使用一种新的XAML(eXtensible Application Markup Language)语言来开发界面,这将把界面开发以及后台逻辑很好的分开,降低了耦合度,使用户界面设计师与程序开发者能更好的合作,降低维护和更新的成本。

注意上面的说明,XAML的使用就是为了降低耦合度。那么我们不得不说说WinForm和WPF的区别了。

1.WinForm更新UI的操作是通过后台操作UI名,即ID来完成的。WPF是通过数据Binding来实现UI更新的。
  2.WinForm响应用户操作的方式是事件Event。WPF是通过命令(Command)Binding的方式。

所以说,从你写的第一个WPF的Hello World开始,你就要转变思路了!而不是很多人做的那种给按钮添加事件,点击触发然后抱怨和过去的Winform没啥区别一点都不好用。。。

上面又扯远了。

好了,开始写第一个MVVM框架。

定义一个NotificationBase类,这个类的作用是实现了INotifyPropertyChanged接口,目的是绑定数据属性。实现了它这个接口,数据属性发生变化后才会去通知UI。如果想在数据属性发生变化前知道,需要实现INotifyPropertyChanging接口。

 using System.ComponentModel;

 namespace mvvw框架示例
{
class NotificationBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged; public void RaisePropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}

OK,下一步。

同样实现了数据属性的可Binding,用来响应用户UI操作的命令也该有了。定义DelegateCommand类。目的是绑定命令属性。这个类的作用是实现了ICommand接口,WPF中实现了ICommand接口的类,才能作为命令绑定到UI。

using System.Windows.Input;

namespace mvvw框架示例
{
class DelegateCommand : ICommand
{
//A method prototype without return value.
public Action<object> ExecuteCommand = null;
//A method prototype return a bool type.
public Func<object, bool> CanExecuteCommand = null;
public event EventHandler CanExecuteChanged; public bool CanExecute(object parameter)
{
if (CanExecuteCommand != null)
{
return this.CanExecuteCommand(parameter);
}
else
{
return true;
}
} public void Execute(object parameter)
{
if (this.ExecuteCommand != null) this.ExecuteCommand(parameter);
} public void RaiseCanExecuteChanged()
{
if (CanExecuteChanged != null)
{
CanExecuteChanged(this, EventArgs.Empty);
}
}
}
}

开始定义Model类。一个属性成员"Now Time",它就是数据属性,继承自NotificationBase类,所以数据属性具有通知功能,它改变后,会知道通知UI更新。一个方法“PrintNowTime”,用来改变属性“Now Time”的值,它通过命令的方式相应UI事件。

namespace mvvw框架示例
{
class Model : NotificationBase
{
private string _NowTime = "Now Time"; public string NowTime
{
get { return _NowTime; }
set
{
_NowTime = value;
this.RaisePropertyChanged("Now Time");
}
} public void PrintNowTime(object obj)
{
this.NowTime += "Now Time :" + System.DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") + System.Environment.NewLine;
} }
}

定义ViewModel类。定义了一个命令属性"PrintCmd",聚合了一个Model对象"model"。这里的关键是,给PrintCmd命令指定响应命令的方法是model对象的“PrintNowTime”方法。

using System;

namespace mvvw框架示例
{
class ViewModel
{
public DelegateCommand PrintCmd { get; set; }
public Model model { get; set; } public ViewModel()
{
this.model = new Model();
this.PrintCmd = new DelegateCommand();
this.PrintCmd.ExecuteCommand = new Action<object>(this.model.PrintNowTime);
}
}
}

定义View。Binding一个model中的NowTime属性到TextBlock的Text和PrintCmd命令到按钮的Command。

<Window x:Class="mvvw框架示例.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="" Width="">
<Grid>
<StackPanel VerticalAlignment="Center" >
<TextBlock Text="{Binding model.NowTime}" Height="" TextWrapping="WrapWithOverflow"></TextBlock>
<Button Command="{Binding PrintCmd}" Height="" Width="">Print Time</Button>
</StackPanel>
</Grid>
</Window>

上面的{Binding  Model.NowTime}也可以写成{Binding  Path = NowTime},是一个意思,前者更直观。

最后需要在MainWindowx.xaml.cs中加上this.DataContext = new ViewModel();表明MainWindowx.xaml这个UI层的数据和命令指定为从ViewModel获得。

运行结果:

aaarticlea/png;base64,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" alt="" />

上一篇:浅谈前端中的mvvm与mvc


下一篇:OpenCV 学习笔记 02 使用opencv处理图像