MVVM模式和在WPF中的實現(二)數據綁定


MVVM模式解析和在WPF中的實現(二)

數據綁定

系列目錄:

MVVM模式解析和在WPF中的實現(一)MVVM模式簡介

MVVM模式解析和在WPF中的實現(二)數據綁定

MVVM模式解析和在WPF中的實現(三)命令綁定

MVVM模式解析和在WPF中的實現(四)事件綁定

MVVM模式解析和在WPF中的實現(五)View和ViewModel的通信 

MVVM模式解析和在WPF中的實現(六)用依賴注入的方式配置ViewModel並注冊消息

0x00 數據綁定要達到的效果

數據綁定要達到什么效果呢,就是在界面中綁定了數據源之后,數據在界面上的修改能反映到綁定源,同時綁定源的修改也能反映到界面上。從界面反映到綁定的數據源是很容易理解的,因為在綁定過程中我們指定了DataContext和Binding的對象,很容易找到綁定的源並修改。但數據源修改時怎么通知界面呢?因為ViewModel中被綁定的屬性並不知道誰綁定了它,如果在ViewModel中存一個View的引用,在數據發生變化時修改View,這無疑又將ViewModel和View耦合在了一起,而且這樣做View中相應的控件沒有開發完善難以進行測試,同樣View中控件類型或名稱發生改變時,ViewModel中相關代碼都需要修改。在WPF中從數據源通知界面發生變化是通過發送通知的方式進行的,你可以想象一個string類型的Property,名字是TestString,在它發生變化時對着View大喊“TestString發生變化了,你們誰綁定了TestString需要跟着變啊!”,至於綁定的是TextBlock的Text,還是Label的Content,還是TextBox的Text,ViewModel並不關心,同樣喊了后結果如何ViewModel也不關心。View在收到這個通知后看有沒有綁定 了TestString的地方,找到了就修改,找不到就不管了,也不會在乎這個通知是哪個類型的ViewModel發的。這樣ViewModel和View就解耦了,誰也不依賴對方。

0x01 INotifyPropertyChanged接口

在WPF中能夠實現ViewModel向View喊話功能的就是INotifyPropertyChanged接口,它就像一個大喇叭一樣,我們實現了這個接口,就可以通過觸發PropertyChanged事件並給出改變的數據源的對象和屬性名稱,以此來通知數據的變化。這個接口的實現是非常簡單的,下圖代碼就是一種非常簡易的實現方式。由於在MVVM中所有的ViewModel和部分Model都需要實現這個接口來達到綁定的效果,因此一般會專門用一個類來實現這個接口,並將這個類作為ViewModel等需要數據更改后發送通知的類的基類。

 

0x02 ObservableCollection<T>集合

NotifyObject貌似把一切都解決了,但是考慮這樣一種情況,有一個List<string>列表顯示人員名單,View中的一個ListBox綁定了這個列表。每次我們添加新成員時,為了能在View中立即看到結果必須調用RaisePropertyChanged方法讓ListBox控件重新加載數據源。這種做法執行了大量的無效操作,就像我們只是改變了屏幕上一小部分內容卻要刷新整個屏幕以更新顯示一樣。如果添加的不是人員而是一種添加動作頻繁發生的操作,這種無效操作會極大影響性能。因此WPF提供了一個ObservableCollection<T>集合,可以將數據項的添加、刪除等反映到View中綁定的控件上而無需我們做任何操作。所以在遇到對集合添加、刪除等操作又需要使用數據綁定時要優先考慮ObservalbeCollection<T>。

0x03 數據綁定的示例

有了NotifyObject這個基類后,我們就可以測試數據綁定了。為了讓示例針對性更強,該示例僅僅用到了數據綁定,未添加命令綁定等其它內容。示例界面如圖所示:

1. 拖動滑塊時,最上面TextBox中的數值會跟着變化,顯示滑塊條的當前值,同時主界面背景色的透明度也會跟着變化。

2. 左下角的DataGrid和右下角的ListBox以及右邊標簽為下拉菜單的ComboBox中的數據都是一樣的。選中這三個控件中的某行時,其它兩個控件也會選中該項。右上方紫色方框內會顯示選中行的信息。

3. 在左下角DataGrid控件、右下角ListBox控件、右上角紫色區域的某一處修改數據時,其它兩處的數據也會隨着修改。

下面說明如何通過數據綁定實現上面的功能。

先說一下主界面的ViewModel,其中有double型屬性DoubleValue,TestData型屬性SelectedData,List<TestData>型屬性TestDataList。這里沒有使用ObservableCollection集合因為不涉及到集合內數據項的動態添加和刪除。如果要使用ObservableCollection也非常簡單,只需要把List<TestData>改為ObservableCollection<TestData>即可。

功能1:Slider的Value、TextBox的Text和DockPanel的Background的Opacity都綁定了ViewModel中的DoubleValue。當拖動滑塊時,Slider的Value發生了變化,會更新ViewModel中的DoubleValue,DoubleValue更新后會調用RaisePropertyChanged方法觸發INotifyPropertyChanged中的PropertyChanged事件,並在事件參數中保存了發生改變的屬性名稱“DoubleValue”,這樣View中綁定了DoubleValue的屬性就要更新數據,TextBox的Text屬性綁定了DoubleValue,所以TextBox更新了Text以顯示最新的Slider的Value。同樣主界面最頂層的布局容器DockPanel的Background中的Opacity也綁定了DoubleValue,更改后的表現就是背景色透明度發生了變化。整個過程如圖中藍色箭頭所示。

功能2:DataGrid、ComboBox、ListBox的ItemsSource都綁定了ViewModel中的TestDataList,所以他們的列表項都是一樣的。在DataGrid中我們顯示了TestData的所有屬性,ComboBox中我們只顯示了StringValue屬性,在ListBox中則重寫了數據項模板,按照我們想要的方式顯示TestData中的BoolValue、AddDateTime、和IntValue。同時這三個控件的SelectedItem也都綁定了ViewModel中的SelectedData,因此當其中一個的選中項發生改變時,其它兩個控件的選中項也會相應發生改變,原理參照功能1。此外右上角紫色區域的幾個TextBox和一個CheckBox分別綁定了SelectedData的不同屬性,因此當SelectedData發生改變時,紫色區域內各個控件的顯示內容也會發生改變。

功能3:因為TestData類也繼承自NotifyObject,而且幾個屬性在發生改變時也會調用RaisePropertyChanged方法發出通知,因此所有綁定了這些屬性的控件也會隨着更新數據。表現出來就是在任何地方修改了TestData中的屬性,所有綁定了這些屬性的控件都會更新。

當然了,還需要在主界面的后台代碼中把DataContext設置為ViewModel的一個實例。

DataContext = new MainWindowViewModel();

其實上面很多功能可以不借助ViewModel來實現的。例如功能1中把TextBox的Text直接綁定到Slider的Value上,同樣功能二中ListBox的SelectedItem也可直接綁定到DataGrid的SelectedItem上,之所以使用ViewModel是為了演示MVVM模式下的數據綁定。

0x04 相關下載

示例代碼:https://github.com/durow/TestArea/tree/master/MVVMTest

 


更多內容歡迎訪問我的博客:http://www.durow.vip


免責聲明!

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



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