Prism安装、MVVM基础概念及一个简单的样例
一:Prism的下載和安裝
1:在http://compositewpf.codeplex.com/上下載最新的包。
下載完畢后,運行之,選擇解壓目錄解壓之。解壓完畢的根目錄下有chm幫助文檔。
2:運行RegisterPrismBinaries.bat注冊Prism組件,注冊完畢才能在VS的引用中直接找到Prism組件,否則需要手動添加這些組件。
3:運行Silverlight Only - Basic MVVM QuickStart.bat可以打開一個MVVM的簡單事例。
二:MVVM理解
1:現在,我們自己創建一個普通的SilverLight樣例,并且將它逐步重構成為MVVM模式。
這個 普通的SL樣例需求有:在界面上放置文本框用來顯示Name和Button用來顯示文本框中的Name的值。
前臺:
后臺:
SL的目錄結構:
2:問題來了
如果我們需要讓頁面的值和Student實例的值保持一致,則必須要讓類型繼承自INotifyPropertyChanged接口,并像下面這樣編碼:
public class Student : INotifyPropertyChanged{string firstName;public string FirstName {get { return firstName;}set {firstName = value; Notify("FirstName"); }}string lastName;public string LastName { get {return lastName;}set { lastName = value;Notify("LastName");}}public Student(string firstName, string lastName){this.firstName = firstName;this.lastName = lastName;}void Notify(string propName){if (PropertyChanged != null){PropertyChanged(this, new PropertyChangedEventArgs(propName));}}#region INotifyPropertyChanged Memberspublic event PropertyChangedEventHandler PropertyChanged;#endregion}如果應用程序中存在多個這樣的類型,則每個類型都要實現自己的Notify方法,這顯然是不合理的。所以,無論是Prism框架,還是輕量級的Mvvm light toolkit,都實現了一個超類來包裝這種需求,在Prism里該超類是NotificationObject,而Mvvm light toolkit中是ObservableObject,當然,毫無例外滴,它們都繼承自INotifyPropertyChanged。
3:現在,我們參照這兩個類型,來實現自己的NotificationObject,以便加深印象
public abstract class NotificationObject : INotifyPropertyChanged{public event PropertyChangedEventHandler PropertyChanged;protected virtual void RaisePropertyChanged(string propertyName){PropertyChangedEventHandler handler = this.PropertyChanged;if (handler != null){handler(this, new PropertyChangedEventArgs(propertyName));}}protected void RaisePropertyChanged(params string[] propertyNames){if (propertyNames == null) throw new ArgumentNullException("propertyNames");foreach (var name in propertyNames){this.RaisePropertyChanged(name);}}protected void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression){var propertyName = ExtractPropertyName(propertyExpression);this.RaisePropertyChanged(propertyName);}public static string ExtractPropertyName<T>(Expression<Func<T>> propertyExpression){if (propertyExpression == null){throw new ArgumentNullException("propertyExpression");}var memberExpression = propertyExpression.Body as MemberExpression;if (memberExpression == null){throw new ArgumentException("PropertySupport_NotMemberAccessExpression_Exception", "propertyExpression");}var property = memberExpression.Member as PropertyInfo;if (property == null){throw new ArgumentException("PropertySupport_ExpressionNotProperty_Exception", "propertyExpression");}var getMethod = property.GetGetMethod(true);if (getMethod.IsStatic){throw new ArgumentException("PropertySupport_StaticExpression_Exception", "propertyExpression");}return memberExpression.Member.Name;}}相應的,Student類型修改為:
public class Student : NotificationObject{string firstName;public string FirstName {get { return firstName;}set {firstName = value; //Notify("FirstName"); this.RaisePropertyChanged("FirstName");}}string lastName;public string LastName { get {return lastName;}set { lastName = value;//Notify("LastName");this.RaisePropertyChanged("LastName");}}public Student(string firstName, string lastName){this.firstName = firstName;this.lastName = lastName;}}4:問題再次出現,經過修改后的Student類型,是什么?
是實體Model,領域Model,還是別的什么?實際上,因為沒有采用任何架構模式,當前的Student類型什么也不是,揉雜了很多功能。它既要負責提供屬性,也要負責控制。
在MVVM架構模式中,和MVC稱謂不同的地方,就是VM(ViewModel)部分。VM負責:接受View請求并決定調用哪個模型構件去處理請求,同時它還負責將數據返回給View進行顯示。也就是說,VM完成的角色可以理解為MVC中的Control。(另外需要注意的一點是,在MVC中有一個概念叫做表現模型,所謂表現模型是領域模型的一個扁平化投影,不應和MVVM中的VIEW MODEL相混淆)。
所以,我們現在要明確這些概念。首先,將Student類型的功能細分化,VM的部分,我們跟頁面名稱對應起來應該叫做MainViewModel。實際項目中,功能頁面會相應名為StudentView.xaml,則對應的VM名便稱之為StudentViewModel.cs。我們繼續重構上面的代碼。
三:建立MVVM的各個部分
首先,建立View文件夾,然后,將MainPage.xmal修改為StudentView.xaml后放置到該目錄下。
其次,簡歷ViewModels文件夾,新建一個類StudentViewModel.cs,放置到該目錄下。
最后,原類型Student需要繼續拆分,將作為領域模型部分的功能獨立出來,放置到DomainModel文件夾下。最后的結果看起來如下:
1:領域模型DomainModel部分
public class Student {string firstName;public string FirstName{get{return firstName;}set{firstName = value;}}string lastName;public string LastName{get{return lastName;}set{lastName = value;}}public Student(){//模擬獲取數據Mock();}public void Mock(){FirstName = "firstName" + DateTime.Now.ToString();LastName = "lastName" + DateTime.Now.ToString();}}2:視圖View部分
3:ViewModel部分
public class StudentViewModel : NotificationObject{public StudentViewModel(){student = new Student();}Student student;public Student Student {get{return this.student;}private set{this.student = value;this.RaisePropertyChanged(() => this.student);}}}4:若干解釋
在這個簡單的事例中,領域模型Student負責獲取數據,而數據來源于何處不是我們關心的重點,所以,我們直接在Student中模擬了獲取數據的過程,即Mock方法。
這相當于完成了一次OneWay的過程,即把后臺數據推送到前臺進行顯示。這只能算是完成跟UI交互的一部分功能。UI交互還需要包括從UI中將數據持久化(如保存到數據庫)。而UI跟后臺的交互,就需要通過命令綁定的機制去實現了。
5:命令綁定
在本里中,我們演示兩類命令,一類是屬性類命令綁定,一類是事件類命令綁定。
首先,我們知道,VM負責UI和領域模型的聯系,所以,綁定所支持的方法一定是在VM中,于是,我們在StudentViewModel中定義一個屬性CanSubmit,及一個方法Submit:
public bool CanSubmit{get{return true;}}public void Submit(){student.Mock();??????? }注意,Submit方法中為了簡單期間,使用了模擬方法。由于Mock方法中仍然可能設計到UI的變動(如隨數據庫的某些具體的值變動而變動),故領域模型Student可能也會需要繼承NotificationObject,在本例中,Student改變為如下:
public class Student : NotificationObject{string firstName;public string FirstName{get{return firstName;}set{firstName = value;this.RaisePropertyChanged("FirstName");}}string lastName;public string LastName{get{return lastName;}set{lastName = value;this.RaisePropertyChanged("LastName");}}public Student(){//模擬獲取數據Mock();}public void Mock(){FirstName = "firstName" + DateTime.Now.ToString();LastName = "lastName" + DateTime.Now.ToString();}}其次,需要改變VIEW,如下:
注意途中紅線框起來的部分。
經過這一次的重構之后,基本滿足了一個簡單的MVVM模型的需要。代碼下載在這里:http://files.cnblogs.com/luminji/SilverlightApplication2.rar
微信掃一掃,關注最課程(www.zuikc.com),獲取更多我的文章,獲取軟件開發每日一練
下一篇講述使用Prism的MVVM框架
總結
以上是生活随笔為你收集整理的Prism安装、MVVM基础概念及一个简单的样例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 对QT学习之路12-14的源代码补充与修
- 下一篇: 推荐15个在线多媒体(图片、音频、视频)