WPF經典編程模式-MVVM示例講解


 

一,MVVM理論知識

  從上一篇文章中,我們已經知道,WPF技術的主要特點是數據驅動UI,所以在使用WPF技術開發的過程中是以數據為核心的,WPF提供了數據綁定機制,當數據發生變化時,WPF會自動發出通知去更新UI。 

  我們使用模式,一般是想達到高內聚低耦合。在WPF開發中,經典的編程模式是MVVM,是為WPF量身定做的模式,該模式充分利用了WPF的數據綁定機制,最大限度地降低了Xmal文件和CS文件的耦合度,也就是UI顯示和邏輯代碼的耦合度,如需要更換界面時,邏輯代碼修改很少,甚至不用修改。與WinForm開發相比,我們一般在后置代碼中會使用控件的名字來操作控件的屬性來更新UI,而在WPF中通常是通過數據綁定來更新UI;在響應用戶操作上,WinForm是通過控件的事件來處理,而WPF可以使用命令綁定的方式來處理,耦合度將降低。

  我們可以通過下圖來直觀的理解MVVM模式:  

  View就是用xaml實現的界面,負責與用戶交互,接收用戶輸入,把數據展現給用戶。
  ViewModel,一個C#類,負責收集需要綁定的數據和命令,聚合Model對象,通過View類的DataContext屬性綁定到View,同時也可以處理一些UI邏輯。
  Model,就是系統中的對象,可包含屬性和行為。

  一般,View對應一個ViewModel,ViewModel可以聚合N個Model,ViewModel可以對應多個View,Model不知道View和ViewModel的存在。

二,MVVM示例講解

  這個示例是為了讓大家直觀地了解MVVM的編程模式,關於其中用到的數據綁定和命令等知識,在后面的文章會專門討論。

  1. 首先定義NotificationObject類。目的是綁定數據屬性。這個類的作用是實現了INotifyPropertyChanged接口。WPF中類要實現這個接口,其屬性成員才具備通知UI的能力,數據綁定的知識,后面詳細討論。
復制代碼
using System.ComponentModel;

namespace WpfFirst
{
    class NotificationObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void RaisePropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}
復制代碼

  2.定義DelegateCommand類。目的是綁定命令屬性。這個類的作用是實現了ICommand接口,WPF中實現了ICommand接口的類,才能作為命令綁定到UI。命令的知識,后面詳細討論。

復制代碼
using System;
using System.Collections.Generic;
using System.Windows.Input;

namespace WpfFirst
{
    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);
            }
        }
    }
}
復制代碼

  3.開始定義Model類。一個屬性成員"WPF",它就是數據屬性,的有通知功能,它改變后,會知道通知UI更新。一個方法“Copy”,用來改變屬性“WPF”的值,它通過命令的方式相應UI事件。

復制代碼
using System.ComponentModel;
using System.Windows.Input;

namespace WpfFirst
{
    class Model : NotificationObject
    {
        private string _wpf = "WPF";

        public string WPF
        {
            get { return _wpf; }
            set
            {
                _wpf = value;
                this.RaisePropertyChanged("WPF");
            }
        }        

        public void Copy(object obj)
        {
            this.WPF += " WPF";
        }
        
    }
}
復制代碼

  4.定義ViewModel類。定義了一個命令屬性"CopyCmd",聚合了一個Model對象"model"。這里的關鍵是,給CopyCmd命令指定響應命令的方法是model對象的“Copy”方法。

復制代碼
using System;
namespace WpfFirst
{
    class ViewModel
    {
        public DelegateCommand CopyCmd { get; set; }        
        public Model model { get; set; }

        public ViewModel()
        {
            this.model = new Model();
            this.CopyCmd = new DelegateCommand();
            this.CopyCmd.ExecuteCommand = new Action<object>(this.model.Copy);
        }
    }
}
復制代碼

  5.定義View.

  MainWindow.xaml代碼:我們能看到,TextBlock控件的text屬性,綁定在model對象的WPF屬性上; Button的click事件通過命令綁定到CopyCmd命令屬性。  

復制代碼
<Window x:Class="WpfFirst.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.WPF}" Height="208" TextWrapping="WrapWithOverflow"></TextBlock>
            <Button Command="{Binding CopyCmd}" Height="93" Width="232">Copy</Button>
        </StackPanel>
    </Grid>
</Window>
復制代碼

  MainWindow.xaml.cs代碼:它的工作知識把ViewModel對象賦值到DataContext屬性,指定View的數據源就是這個ViewModel。

復制代碼
using System.Windows;

namespace WpfFirst
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            this.DataContext = new ViewModel();
        }
    }
}
復制代碼

  6.運行結果。每當我們點擊按鈕,界面就是被更新了,因為Copy方法改變了WFP屬性的值。  

  寫這個簡單的例子,就是為了直觀地了解MVVM的編程模式。在實際開發中,不管程序有多復雜,也就是增加Model, View, ViewModel,和其他的一些輔助類(Helpers or Services)了,模式不會改變。


免責聲明!

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



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