最近在研究学习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更新的。WinForm响应用户操作的方式是事件Event。WPF是通过命令(Command)Binding的方式。
所以说,从你写的第一个WPF的Hello World开始,你就要转变思路了!而不是很多人做的那种给按钮添加事件,点击触发然后抱怨和过去的Winform没啥区别一点都不好用。。。
上面又扯远了。
好了,开始写第一个MVVM框架。
INotifyPropertyChanging接口。
1 using System.ComponentModel;
2
3 namespace mvvw框架示例
4 {
5 class NotificationBase : INotifyPropertyChanged
6 {
7 public event PropertyChangedEventHandler PropertyChanged;
8
9 public void RaisePropertyChanged(string propertyName)
10 {
11 if (this.PropertyChanged != null)
12 {
13 this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
14 }
15 }
16 }
17 }
OK,下一步。
定义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;
}
}
}
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="350" Width="525">
<Grid>
<StackPanel VerticalAlignment="Center" >
<TextBlock Text="{Binding model.NowTime}" Height="208" TextWrapping="WrapWithOverflow"></TextBlock>
<Button Command="{Binding PrintCmd}" Height="60" Width="100">Print Time</Button>
</StackPanel>
</Grid>
</Window>
上面的{Binding Model.NowTime}也可以写成{Binding Path = NowTime},是一个意思,前者更直观。
最后需要在MainWindowx.xaml.cs中加上this.DataContext = newViewModel获得。
运行结果: