1. 程式人生 > >WPF快速入門系列(8)——MVVM快速入門

WPF快速入門系列(8)——MVVM快速入門

http://www.cnblogs.com/zhili/p/MVVMDemo.html

一、引言

  在前面介紹了WPF一些核心的內容,其中包括WPF佈局、依賴屬性、路由事件、繫結、命令、資源樣式和模板。然而,在WPF還衍生出了一種很好的程式設計框架,即WVVM,在Web端開發有MVC,在WPF客戶端開發中有MVVM,其中VM就相當於MVC中C(Control)。在Web端,微軟開發了Asp.net MVC這樣的MVC框架,同樣在WPF領域,微軟也開發了Prism這樣的MVVM框架。Prism專案地址是:http://compositewpf.codeplex.com/SourceControl/latest

。大家有興趣的可以下載原始碼研究下。

二、MVVM模式是什麼?

  既然講到MVVM模式,自然第一個問題就是MVVM的含義。MVVM是Model-View-ViewModel的縮寫形式,它通常被用於WPF或Silverlight開發。這三者之間的關係如下圖所示:

  下面我們分別來介紹下這三部分。

模型(Model)

  Model——可以理解為帶有欄位,屬性的類。

檢視(View)

  View——可以理解為我們所看到的UI。

檢視模型(View Model)

View Model在View和Model之間,起到連線的作用,並且使得View和Model層分離。View Model不僅僅是Model的包裝,它還包含了程式邏輯,以及Model擴充套件,例如,如果Model中有一個公開屬性不需要在UI上顯示,此時我們可以不再View Model中去定義它。

在MVVM模式下,WPF程式的執行流程如下圖所示:

  在MVVM中,VM的地位可以說是舉足輕重。使用MVVM模式具有以下幾個特點:

  • 檢視的cs檔案包括極少的程式碼,其核心邏輯都被放在View Model類中,從而使得程式邏輯與檢視耦合度降低。
  • ViewModel類作為View的DataContext。
  • 在MVVM下,所有的事件和動作都被當成命令,如按鈕的點選操作,此時不是觸發點選事件,而是繫結到一個點選命令,再由命令去執行對應的邏輯。

三、使用MVVM模式來實現WPF程式

  前面介紹了MVVM一些基礎知識,下面通過一個例項來說明下如何在WPF程式中應用MVVM模式。在之前實現WPF程式時,我們可能會把所有的後臺邏輯都放在檢視的後臺檔案中,這樣的實現方式的好處更直觀,方便,對於一些小的應用程式這樣做當然沒什麼問題,但是對於複雜的應用程式這樣寫的話,可能會導致後臺程式碼顯得非常臃腫,到最好變得難以維護。此時想到的解決方案就是職責分離,使後臺的邏輯分離到其他類中,MVVM其實我理解就是達到這個目的。下面我們按照MVVM的組成部分來實現下這個MVVM程式。

  第一步:自然是資料部分了,即Model層的實現。在這裡定義了一個Person類,其中包含了2個基本的屬性。

public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }

  為了進行測試,下面建立一個靜態方法來獲得測試資料。

複製程式碼
public class PersonDataHelper
    {
        public static ObservableCollection<Person> GetPersons()
        {
            ObservableCollection<Person> samplePersons = new ObservableCollection<Person>();
            samplePersons.Add(new Person() {Name = "張三", Age = 33});
            samplePersons.Add(new Person() { Name ="王五", Age= 22 });
            samplePersons.Add(new Person() { Name = "李四", Age = 35 });
            samplePersons.Add(new Person() { Name = "LearningHard", Age = 27 });
            return samplePersons;
        }
    }
複製程式碼

  第二步:實現ViewModel層,實現資料和介面之間的邏輯。在檢視模型類中,包含了屬性和命令,因為在MVVM中,事件都當成命令來進行處理,其中命令只能與具有Command屬性的控制元件進行繫結。既然要包含命令,首先就需要實現一個命令,這裡自定義的命令需要實現ICommand介面。這裡我們定義了一個QueryCommand。具體的實現程式碼如下所示:

複製程式碼
public class QueryCommand :ICommand
    {
        #region Fields
        private Action _execute;
        private Func<bool> _canExecute;
        #endregion 

        public QueryCommand(Action execute)
            : this(execute, null)
        { 
        }
        public QueryCommand(Action execute, Func<bool> canExecute)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");
            _execute = execute;
            _canExecute = canExecute;
        }

        #region ICommand Member

        public event EventHandler CanExecuteChanged
        {
            add
            {
                if (_canExecute != null)
                {
                    CommandManager.RequerySuggested += value;

                }
            }
            remove
            {
                if (_canExecute != null)
                {
                    CommandManager.RequerySuggested -= value;

                }
            }
        }

        public bool CanExecute(object parameter)
        {
            return _canExecute == null ? true : _canExecute();
        }

        public void Execute(object parameter)
        {
            _execute();
        }
        #endregion
    }
複製程式碼

  接下來就是定義我們的ViewModel類了,具體的實現程式碼如下所示:

複製程式碼
 1 public class PersonListViewModel : INotifyPropertyChanged
 2     {
 3         #region Fields
 4         private string _searchText;
 5         private ObservableCollection<Person> _resultList;
 6         #endregion 
 7 
 8         #region Properties
 9 
10         public ObservableCollection<Person> PersonList { get; private set; }
11 
12         // 查詢關鍵字
13         public string SearchText
14         {
15             get { return _searchText; }
16             set
17             {
18                 _searchText = value;
19                 RaisePropertyChanged("SearchText");
20             }
21         }
22 
23         // 查詢結果
24         public ObservableCollection<Person> ResultList
25         {
26             get { return _resultList; }
27             set
28             {
29                 _resultList = value;
30                 RaisePropertyChanged("ResultList");
31             }
32         }
33 
34         public ICommand QueryCommand 
35         { 
36             get { return new QueryCommand(Searching, CanSearching); } 
37         }
38 
39         #endregion 
40 
41         #region Construction
42         public PersonListViewModel()
43         {
44             PersonList = PersonDataHelper.GetPersons();
45             _resultList = PersonList;
46         }
47 
48         #endregion
49         
50         #region Command Handler
51         public void Searching()
52         {
53             ObservableCollection<Person> personList = null;
54             if (string.IsNullOrWhiteSpace(SearchText))
55             {
56                 ResultList = PersonList;
57             }
58             else
59             {
60                 personList = new ObservableCollection<Person>();
61                 foreach (Person p in PersonList)
62                 {
63                     if (p.Name.Contains(SearchText))
64                     {
65                         personList.Add(p);
66                     }
67                 }
68                 if (personList != null)
69                 {
70                     ResultList = personList;
71                 }
72             }
73         }
74 
75         public bool CanSearching()
76         {
77             return true;
78         }
79 
80         #endregion 
81 
82         #region INotifyPropertyChanged Members
83 
84         public event PropertyChangedEventHandler PropertyChanged;
85 
86         #endregion
87 
88         #region Methods
89         private void RaisePropertyChanged(string propertyName)
90         {
91             // take a copy to prevent thread issues
92             PropertyChangedEventHandler handler = PropertyChanged;
93             if (handler != null)
94             {
95                 handler(this, new PropertyChangedEventArgs(propertyName));
96             }
97         }
98         #endregion 
99     }
複製程式碼

  第三步:實現View層,設計我們的檢視,設定它的DataContext屬性為ViewModel類。具體的XAML程式碼如下所示:

複製程式碼
<Window x:Class="MVVMDemo.View.PersonsView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:MVVMDemo.ViewModel"
        Title="PersonsView" Height="350" Width="400">
    <!--設定DataContex是ViewModel類,當然你也可以使用後臺程式碼設定-->
    <Window.DataContext>
        <local:PersonListViewModel />
    </Window.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <TextBox Grid.Row="0" Name="searchtxt" Text="{Binding  Path=SearchText, Mode=TwoWay}" HorizontalAlignment="Left" Height="30" Width="280" Margin="10,0,0,0"></TextBox>
        <Button Grid.Row="0" Name="searchBtn" Content="Search" Command="{Binding Path=QueryCommand}" Width="80" Height="30" HorizontalAlignment="Right" Margin="0,0,10,0"></Button>
        <DataGrid Grid.Row="1" Name="datGrid" 
                  HorizontalAlignment="Center"
                  VerticalAlignment="Top" ItemsSource="{Binding Path=ResultList}" Width="300"></DataGrid>
        
    </Grid>
</Window>
複製程式碼

  到此,我們的MVVM的WPF程式就已經完成了,下面就是要看看程式是否達到我們預期的目的。具體的執行結果如下圖所示:

四、總結

  到這裡,本文的內容就分享完了,並且本文也是WPF系列的最後一篇了,希望這個系列可以使得初學者快速上手WPF程式設計。在接下來的時間裡,我打算寫一些具有實戰性的內容,因為我之前都是分享一些初級的入門系列,接下來打算分享一些實際的專案實現,以及領域驅動設計方面的內容,希望得到大家的督促和支援。


相關推薦

WPF快速入門系列(8)——MVVM快速入門

http://www.cnblogs.com/zhili/p/MVVMDemo.html 一、引言   在前面介紹了WPF一些核心的內容,其中包括WPF佈局、依賴屬性、路由事件、繫結、命令、資源樣式和模板。然而,在WPF還衍生出了一種很好的程式設計框架,即WVV

linux入門系列8--shell程式設計入門

本文將結合前面介紹的Linux命令、管道符等知識,通過VI編輯器編寫Shell指令碼,實現能自動化工作的指令碼檔案。 在講解Linux常用命令“linux入門系列5--新手必會的linux命令”一文中已提到,Shell終端直譯器是人機互動的橋樑,是使用者與核心之間的翻譯官。它作為使用者與Linux系統內部通訊

企業級Hadoop 2.x入門系列之十二入門視訊分享

 網上流傳非常好的《Hadoop 2.x入門學習視訊》,在此將網盤下載地址分享給大家 課程相關【軟體與工具】:     連結:http://pan.baidu.com/s/1hqEGFQk 密碼:b4sh 第一次課程:    連結:http://pan.baidu.com/

WPF/MVVM 快速入門教程

簡介 先假設大家對c#已經有一定的瞭解了,並且很容易接受一些關於WPF的知識。因為下面的知識是通過WPF為例的。 我前段時間開始研究了一下WPF,但是找不到什麼有幫助的關於MVVM的教程。因此我希望這篇文章能讓你眼前一亮。 當我們剛開始學一門新技術時,我們得益於前人的積

快速入門系列--WCF--07傳輸安全、授權與審核

最大的 緩存 ims cut 常見 曾經 strong 這一 set 這部分主要涉及企業級應用的安全問題,一般來說安全框架主要提供3個典型的安全行為:認證、授權和審核。除了典型的安全問題,對於一個以消息作為通信手段的分布式應用,還需要考慮消息保護(Message Prote

快速入門系列

body 現在 安全 behavior 需求 discovery 中心 驗證 溝通 最後一章將進行WCF擴展和新特性的學習,這部分內容有一定深度,有一個基本的了解即可,當需要自定義一個完整的SOA框架時,可以再進行細致的學習和實踐。 服務端架構體系的構建主要包含接下來

快速入門系列--WCF--02消息、會話與服務寄宿

abc align bsp 不同的 cpu .org 程序 伸縮 網絡 經過WCF基礎的ABC學習,已經可以構建簡單的WCF的服務,使用不同的服務地址和綁定類型,根據業務提供所需的服務契約。但不禁想問,服務所使用的消息報文是什麽樣的形式麽?蘊含什麽樣內容呢?WCF服務是否支

快速入門系列--WebAPI--03框架你值得擁有

let lan 最重要的 reason cnblogs err 註意 解釋 max 接下來進入的是俺在ASP.NET學習中最重要的WebAPI部分,在現在流行的互聯網場景下,WebAPI可以和HTML5、單頁應用程序SPA等技術和理念很好的結合在一起。所謂ASP.N

快速入門系列--WebAPI--01基礎

簡單例子 codec 應該 sem ons 請求重定向 選擇 char 阻止 ASP.NET MVC和WebAPI已經是.NET Web部分的主流,剛開始時兩個公用同一個管道,之後為了更加的輕量化(WebAPI是對WCF Restful的輕量化),WebAPI使用了新的管道

快速入門系列--MVC--06視圖

出版 value 快速入門 stream 類型 path .cn esc eba 到了View的呈現板塊,感覺ASP.NET MVC的學習也進入了尾聲,還是比較開心的,畢竟也有了不小收獲。這部分內容相對比較簡單,因為之前還專門學習過如何結合HTML5與MVC框架。前

快速入門系列--CLR--03泛型集合

value mov nts readonly 只有一個 並且 cer view 工作 .NET中的泛型集合 在這裏主要介紹常見的泛型集合,很多時候其並發時的線程安全性常常令我們擔憂。因而簡述下.NET並發時線程安全特性,其詳情請見MSDN。 普通集合都不支持多重並發寫操

(5)Jquery1.8.3快速入門

code nextall first 當前 tex title cli AR UNC 一、Jquery的選擇器: 層級選擇器; 1、空格 div span div中的包含的所有span後代元素 2、 &

(6)Jquery1.8.3快速入門

ima jquery ade 過濾器 偶數 head function dex PE 一、Jquery的基本過濾選擇器: 基本過濾選擇器: 1、 :first 選取第一個元素 2、 :last 選取最後一個元素 3、:not(selector) 去除所有與給定

(8)Jquery1.8.3快速入門

isa PE tex utf pla 技術 doctype input meta 一、Jquery的可見性選擇器: 可見性選擇器: 1、:visable 篩選可以見的元素 2、 :hidden 篩選不可見的元素 效果: 源碼: <!DOCTYPE htm

十五分鐘快速入門系列:Python基礎

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Docker 快速入門系列

Docker 是一個開源的應用容器引擎,基於 Go 語言並遵從 Apache2.0 協議開源。 本 Chat 的主要內容如下: Docker 的基本理論概述(萬丈高樓平地起嘛); 理解 Docker&容器; CentOS-7.5下 快速安裝 Docker; CentOS

爬蟲入門系列(一):快速理解HTTP協議

爬蟲入門系列目錄: 4月份給自己挖一個爬蟲系列的坑,主要涉及HTTP 協議、正則表示式、爬蟲框架 Scrapy、訊息佇列、資料庫等內容。 爬蟲的基本原理是模擬瀏覽器進行 HTTP 請求,理解 HTTP 協議是寫爬蟲的必備基礎,招聘網站的爬蟲崗位也赫然寫著熟練掌握HTTP協議規範,寫

Spring Boot 2.0 WebFlux 上手系列課程:快速入門(一)

02:WebFlux 快速入門實踐 Spring Boot 2.0 spring.io 官網有句醒目的話是: BUILD ANYTHING WITH SPRING BOOT Spring Boot (Boot 顧名思義,是引導的意思)框架是用於簡

[Qt Creator 快速入門] 第8章 介面外觀

  一個完善的應用程式不僅應該有實用的功能,還要有一個漂亮的外觀,這樣才能使應用程式更加友好,更加吸引使用者。作為一個跨平臺的UI開發框架,Qt提供了強大而靈活的介面外觀設計機制。這一章將學習在Qt中設計應用程式外觀的相關知識,會對Qt 風格QStyle和調色盤QPalette進行簡單介紹,然後再對Qt樣式表

Scala程式設計快速入門系列(一)

目    錄 一、Scala概述 二、Scala資料型別 三、Scala函式 四、Scala集合 五、Scala伴生物件 六、Scala trait 七、Actor 八、隱式轉換與隱式引數 九、Scala JDBC 由於整理的篇幅較長,所以文章計劃分三次釋出。