简单的介绍下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接口。

 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,下一步。

  同样实现了数据属性的可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="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 = new ViewModel();表明MainWindowx.xaml这个UI层的数据和命令指定为从ViewModel获得。

运行结果:

原文地址:https://www.cnblogs.com/Mushrooms/p/3794849.html