Model View ViewModel(MVVM)是在 Silverlight 和 WPF 項目開發中應用最多的結構模式,也是 Silverlight 和 WPF 項目開發的最佳模式。本文的主要目的不是講解 MVVM 模式。目前已有很多 MVVM 框架可以用來簡化 MVVM 開發,如 Prism、SilverlightFX、MvvmLight、Caliburn、Simple MVVM Toolkit等。
本文將使用 MvvmLight 框架來演示如何在 MVVM 模式下與子窗體交互,即如何在 ViewModel 中彈出一個子窗體。 在 程序開發中經常會遇到諸如彈出提示框、確認框、用戶輸入窗口等的情況,在 Silverlight 中這些情況都可以用子窗體(Child Window)來處理。在未使用 MVVM 模式的情況下,我們可以在用戶控件或頁面的後置代碼(Code Behind)中實例化一個子窗體,調用子窗體的 Show 方法來彈出子窗體,然後通過子窗體的 Closed 方法用戶的操作結果。但是在使用
MVVM 模式的情況下,爲了使 Model 和 View 最大限度的分離,我們要使用儘可能少的後置代碼。如果在後置代碼中實例化並顯示子窗體,這就使用代碼和視圖結合在一起了;當然也可以在 ViewModel 裏實例化並顯示子窗體,這樣又使子窗體和 ViewModel 結合在一起了。
首先我們來看一下示例程序的運行結果:
程序運行後當用戶單擊 New Customer 按鈕時,就會彈出一個子窗體,用戶輸入Customer Id、Customer Name、Customer City 後單擊 OK 按鈕就會在主頁面的客戶列表中顯示出剛纔輸入的客戶信息。下面是本示例具體的實現。
新 建一個 Silverlight 項目,然後在項目中添加Views、Models、ViewModels、Locators文件夾(如果是通過 MvvmLight 模板創建的 Silverlight 項目,默認 ViewModel Locator 和 ViewModel 在同一文件夾中)。添加對程序集 GalaSoft.MvvmLight.Extras.SL4 和 GalaSoft.MvvmLight.SL4 的引用(如果通過 MvvLight 模板創建則會自動引用)。在 Model 文件夾中新建一個 Customer Model,完整代碼如下:
01 public class Customer : INotifyPropertyChanged
02 {
03 private string customerId;
04 public string CustomerId
05 {
06 get { return customerId; }
07 set
08 {
09 customerId = value;
10 NotifyPropertyChanged("CustomerID");
11 }
12 }
13
14 private string customerName;
15 public string CustomerName
16 {
17 get { return customerName; }
18 set
19 {
20 customerName = value;
21 NotifyPropertyChanged("CustomerName");
22 }
23 }
24
25 private string city;
26 public string City
27 {
28 get { return city; }
29 set
30 {
31 city = value;
32 NotifyPropertyChanged("City");
33 }
34 }
35
36 public event PropertyChangedEventHandler PropertyChanged;
37
38 public void NotifyPropertyChanged(string propertyName)
39 {
40 if (PropertyChanged != null)
41 PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
42 }
43 }
下面是 MainPage 的後置代碼:
|
從上面的代碼中可以看到,我使用 MvvmLight 的 Messenger 在主窗體中註冊了一個消息接收者,用於接收 ViewModel 發來的消息並彈出子窗體。下面是子窗體 NewCustomerView 的後置代碼:
|
我同樣在子窗體中也註冊一個消息接收者,接收 ViewModel 發來的消息並關閉子窗體。注意主窗體中註冊的消息接收者的 Token 爲 “MainWindow”,子窗體中註冊的消息接收者的 Token 爲 “ChildWindow”,在 ViewModel 中發送消息時,只有與發送的消息的 Token 相同的接收者才收到消息。下面是 MainViewModel 的代碼,這裏只是爲了演示,主窗體和子窗體共用了一個 ViewModel。
|
在 ViewModel 中也註冊了一個消息接收者,用於接收子窗體返回的數據。ViewModel 中的 NewCustomerCommand 是綁定到主窗體的 NewCustomer 按鈕的,單擊按鈕 NewCustomer 時調用 NewCustomer() 方法向主窗體發送一個消息, 主窗體接收到消息後彈出子窗體。ViewModel 中的 OKButtonCommand 是綁定到子窗體的 OKButton 的,單擊按鈕 OKButton 時調用 OKButtonClick() 向子窗體和 ViewModel 發送一個消息,子窗體接收到消息時關閉,ViewModel 接收到消息時將參數 Customer 添加 Customer 列表中。以下是按鈕的事件綁定代碼:
|
本示例只是提供一個在 MVVM 模式下與子窗體交互的解決方法,這個解決方法也並不是純粹的 MVVM,完整的示例請查看附件的示例代碼。