• 简单的介绍下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获得。

    运行结果:

  • 相关阅读:
    CSS笔记
    EasyUI笔记
    EasyUI treegrid 获取编辑状态中某字段的值 [getEditor方法获取不到editor]
    2019.10.12解题报告
    %lld 和 %I64d
    关于kmp算法
    洛谷p2370yyy2015c01的U盘题解
    About me & 友链
    关于Tarjan
    洛谷p3398仓鼠找suger题解
  • 原文地址:https://www.cnblogs.com/Mushrooms/p/3794849.html
Copyright © 2020-2023  润新知