簡單的介紹下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獲得。

運行結果:

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM