Hello MVVM

关于什么是MVVM partten,及MVVM partten的相关理论介绍这篇博文就不多说了,各位可以去看下Youtube相关的tutorial。

LZ也是在Youtube、CodePlex和CodeProject上看了许久的教材后,写下了这篇博文,类似的例子外文的网站上很多。写作这篇随笔的目的是,感受一下如何写一个MVVM的WPF 程序。MS的WPF MVP刘铁锰给的一个视频对MVVM的介绍也不错,示例也很好。作为一个MVVM的初学者,希望能通过这篇博文,展现MVVM代码的写作流程。

Beginer to Beginer,为此,LZ在代码中添加了必要的说明。

我们的Demo设计的界面如下:

<Window x:Class="MVVMPro1.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>

        <Grid.RowDefinitions>

            <RowDefinition Height="40"/>

            <RowDefinition Height="40"/>

            <RowDefinition Height="40"/>

            <RowDefinition Height="*"/>

        </Grid.RowDefinitions>

        <TextBox Grid.Row="0" FontSize="26" />

        <TextBox Grid.Row="1" FontSize="26" />

        <TextBox Grid.Row="2" FontSize="26" />

        <Button  Grid.Row="3" Content="Add" />

    </Grid>

</Window>

非常的简洁,现在要实现的功能是在点击Button,在第三个TextBox中显示钱两个TextBox的Text属性的连接。
--------------------

对于这样一个程序,不用MVVM可能就一行代码就搞定了:为Button添加Click事件,并在其事件处理中写上类似这么的一条语句:

TextBox3.Text=TextBox1.Text+TextBox2.Text;

当然事实也是这样,完全可以不用MVVM模式!

MVVM的诸多优点。。。。”

MVVM优点,主要目的是通过分离视图(View)和模型(Model),(个人认为:一切模式的最终目标是降低项目成本!)有几大优点  
1. 低耦合

  视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model不可以不变,当Model变化的时候View也可以不变。   
2. 可重用性。

  你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。   
3. 独立开发。

  开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression Blend可以很容易设计界面并生成xaml代码。   
4. 可测试。

  界面素来是比较难于测试的,而现在测试可以针对ViewModel来写。

-------------------------------------

好吧!下面看用MVVM如何来写,不借助Prism等框架,我们纯手工来写。

我们可以在项目中添加几个文件夹以方便整个项目的管理。

Hello MVVM

1.在ViewModels文件夹中添加一个类NotificationObject,这个类是我们所有ViewModel的基类,实现INotifyPropertyChanged接口,还记得前面这个接口?。

using System.ComponentModel;



namespace MVVMPro1.ViewModels

{

    /// <summary>

    /// ViewModel的基类

    /// </summary>

    class NotificationObject:INotifyPropertyChanged

    {

        #region INotifyPropertyChanged 成员



        public event PropertyChangedEventHandler PropertyChanged;



        #endregion

        

        //定义一个方法封转这个事件

        public void RaisePropertyChange(string propertyName)

        {

            if (PropertyChanged !=null)

            {

                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));

            }

        }

    }

}

 2.在Commands文件夹中添加一个DelegateCommand命令,实现ICommand接口:

using System;

using System.Windows.Input;



namespace MVVMPro1.Commands

{

    /// <summary>

    /// MVVM命令使用的事件

    /// </summary>

    class DelegateCommand:ICommand

    {

        #region ICommand 成员



        public bool CanExecute(object parameter)

        {

            if (CanExecuteFunc == null)

            {

                return true;

            }

            return CanExecuteFunc(parameter);

        }



        public event EventHandler CanExecuteChanged;



        public void Execute(object parameter)

        {

            if (ExecuteAction == null)

            {

                return;

            }

            ExecuteAction(parameter);

        }



        #endregion



        public Action<object> ExecuteAction { get; set; }

        public Func<object, bool> CanExecuteFunc { get; set; }

    }

}

3.有了以上1-2准备,我们可以为MainWindow这个View实现一个ViewModel了,在ViewModels文件夹中添加一个MainWindowViewModel类,继承自1定义的NotificationObject类,如下。注意其中的注释部分,这是MVVM模式不容易理解的地方!

using System;

using MVVMPro1.Commands;



namespace MVVMPro1.ViewModels

{

    class MainWindowViewModel:NotificationObject 

    {

        //MainWindow有2个输入,1个输出,对应3个“数据属性”

        private string input1;

        public string Input1

        {

            get { return input1; }

            set 

            {

                input1 = value;

                RaisePropertyChange("Input1");

            }

        }

        private string input2;

        public string Input2

        {

            get { return input2; }

            set

            {

                input2 = value;

                RaisePropertyChange("Input2");

            }

        }

        private string output1;

        public string Output1

        {

            get { return output1; }

            set

            {

                output1= value;

                RaisePropertyChange("Output1");

            }

        }

        //一个Button,共一个“命令属性”

        public DelegateCommand AddCommand{get;set;}

        private void Add(object parameter)

        {

            Output1 = Input1 + Input2;

        }

        //Ctor中进行关联

        public MainWindowViewModel()

        {

            AddCommand = new DelegateCommand();

            AddCommand.ExecuteAction = new Action<object>(Add);

        }



    }

}

 4.为MainWindow添加数据Binding,注意其中的Binding部分

<Window x:Class="MVVMPro1.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>

        <Grid.RowDefinitions>

            <RowDefinition Height="40"/>

            <RowDefinition Height="40"/>

            <RowDefinition Height="40"/>

            <RowDefinition Height="*"/>

        </Grid.RowDefinitions>

        <TextBox Grid.Row="0" FontSize="26" Text="{Binding Input1}"/>

        <TextBox Grid.Row="1" FontSize="26" Text="{Binding Input2}"/>

        <TextBox Grid.Row="2" FontSize="26" Text="{Binding Output1}"/>

        <Button  Grid.Row="3" Content="Add" Command="{Binding AddCommand}"  />

    </Grid>

</Window>
using System.Windows;

using MVVMPro1.ViewModels;



namespace MVVMPro1

{

    /// <summary>

    /// MainWindow.xaml 的交互逻辑

    /// </summary>

    public partial class MainWindow : Window

    {

        public MainWindow()

        {

            InitializeComponent();

            //不要忘了这里

            this.DataContext = new MainWindowViewModel();

        }

    }

}

OK了,Demo下过如下:

Hello MVVM

  OK,这样就OK了,注意不使用MVVM模式与使用MVVM模式程序的区别。

  MVVM实现了View(UI)的分离,只要程序的需求没有本质的变更,需要更改界面,只需要把相应的Binding添加到更新后的界面位置就OK了,ViewModel都不用动!

  小结:这个例子很初级,学习也是一个循序渐进的过程。这个Demo本身没有什么价值,希望能通过它来有一个具体的东西来消化MVVM的抽象的讲解。没有什么可圈可点的地方,因此写个自己吧,作为一种沉淀的方式。个人倒是很喜欢诸如YouTube、CodeProject、CodePlex等外文网站的关于MVVM的讲解,老外的东西确实不错!

  MVVM 完全不一样的开发理念!静下心来,理解它,并感受它的美!

  没什么高端的东西,请关注后续博文~

你可能感兴趣的:(EL)