1. 程式人生 > >Note7:MVVM模式之數據綁定

Note7:MVVM模式之數據綁定

!= lan 發生 xpath 在一起 枚舉 mini tail 自動更新

一、資源說明

(1)本文參考自:

  • 一步步走進WPF的MVVM模式(二):數據綁定
  • WPF之數據綁定總結

二、正文

數據綁定 (Data Binding)是WPF最重要的特性之一,也是實現 MVVM(WPF) 模式的一大支柱。 簡而言之,數據綁定就是將兩個屬性綁定在一起,源屬性(source)改變帶動目標屬性(target)一起改變。這樣也減少了事件(Events)的使用。 綁定源可以是任意對象的屬性,而目標必須是依賴對象的依賴屬性。 綁定源主要分為以下幾種場景(後面主要介紹前兩種):
(1)依賴對象(DependencyObject):可以綁定到任意依賴對象的依賴屬性。
(2)CLR對象:可以綁定到任意CLR對象的公共屬性、子屬性以及索引器。綁定引擎使用CLR反射來獲取屬性值。
(3)動態對象:可以綁定到對象的可用屬性和索引器,該對象實現 IDynamicMetaObjectProvider 接口。
(4)ADO.NET對象:可以綁定到ADO.NET對象,如 DataTable 。ADO.NET DataView 實現 IBindingList 接口,該接口提供綁定引擎偵聽的更改通知。
(5)XML對象:可以綁定到並運行 XmlNode 、 XmlDocument 或 XmlElement 上的 XPath 查詢。
  • 元素對元素的綁定

一種典型的場景是元素對元素的綁定(Element to Element binding),當一個元素屬性發生改變,界面上另外綁定的元素屬性也隨之改變。

<stackpanel>
    <textbox fontsize="{Binding ElementName=slider,Path=Value}" text="Welcome to WPF world." name="txt" />
    <slider name="slider" maximum="26" minimum="14" />
    <textblock text="{Binding ElementName=slider,Path=Value}" name="block" />
</stackpanel>

當我們拖動Slider的時候, TextBox 中字體的大小會隨之改變,下方 TextBlock 中也會更新值。數據綁定利用XAML中 binding 關鍵字,設置它的 ElementNamePath 屬性。也可以在代碼中設置:

Binding bind = new Binding
{
    Source = this.slider,
    Path = new PropertyPath("Value")
};

BindingOperations.SetBinding(this.txt, TextBox.FontSizeProperty, bind);
BindingOperations.SetBinding(this.block, TextBlock.TextProperty, bind);

這在自定義控件中用的比較多。

上面的例子中都遵循著"數據源到目標"的 數據流方向 ,叫做"OneWay"的形式。WPF支持以下幾種數據流方向:

(1)OneWay:綁定源更改時,更新綁定目標屬性。
(2)TwoWay:導致對源屬性或目標屬性的更改可自動更新對方。
(3)OneTime:當應用程序啟動或數據上下文更改時,更新綁定目標。比如用在命令(commands)上面。
(4)OneWayToSource:當目標屬性更改時更新源屬性。當目標屬性不是依賴屬性,而源屬性是依賴屬性的情況下,這就派上用場了。
(5)Default:使用綁定目標的默認Mode值。TextBox.Text屬性默認是TwoWay綁定,而大部分情況下,比如TextBlock.Text屬性就是OneWay綁定。

那麽何時觸發綁定呢?WPF為我們提供了 UpdateSourceTrigger 屬性,這是一個枚舉值: LostFocus , PropertyChanged , Explicit , Default 。從字面意思也能知道何時觸發。需要註意的是,這個屬性只有當 Mode 被設置為 TwoWay 或者 OneWayToSource 的時候才能生效。

我們也可以手動觸發綁定:

var expr = BindingOperations.GetBindingExpression(this.txt, TextBox.FontSizeProperty);
expr.UpdateSource();
//or
expr.UpdateTarget();
  • 綁定到CLR對象

這是最常用的一種情形了。

技術分享

當程序初始化的時候,某個人的年齡數值為10。一旦我點擊了下面的Button,那麽上面的數值會立刻變成30:

技術分享

這裏,我們沒有在Button的 Click 事件裏直接改變中間TextBlock控件的 Text 屬性,而是改變了這個 Person 對象的 Age 值,而最終的效果就是這個TextBlock控件的 Text 屬性也跟著改變了。Data Binding機制在中間起到橋梁的作用。下面,我們來看看 Person 類的實現細節:

public class Person:INotifyPropertyChanged
{
        
    public Person(int _age)
    {
        age = _age;
    }

    private int age;
    public int Age
    {
        get { return age; }
        set
        {
            if (PropertyChanged != null)
            {
                //follow below order
                age = value;
                PropertyChanged(this, new PropertyChangedEventArgs("Age"));
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;  
}

這個Person類實現了 INotifyPropertyChanged 接口(命名空間:System.ComponentModel),這個接口是WPF中數據綁定的核心接口。換言之,如若要想讓CLR對象被成功綁定,那麽這個接口就是必須的。這個接口只包括一個事件 PropertyChanged

Person 類內部包含一個屬性 Age ,在其Setter中有一些邏輯,當然也是很容易懂的。如果這個屬性被改變了,那麽做一些更改,並向外部發出一些通知。

當然,你也可以將 Person 類繼承 DependencyObject 類,讓這個類變成依賴對象,裏面的屬性也就變成了依賴屬性。但是,不建議這樣做。

將需要被綁定的CLR對象實現 INotifyPropertyChanged 接口,這就是全部的準備工作了。

還有一種常見的情況:需要綁定一個集合對象,比如ListBox控件。這個時候,我們需要將這個集合對象繼承自 ObservableCollection<T> 類即可,在後面MVVM框架的內容中會對此有進一步的理解。

數據綁定的核心就是上面介紹的,但是綁定的過程中肯定會遇到一些細節問題,幸好WPF為我們提供了很多機制,可以參考這些介紹做一個了解:

  • 數據模板(data template): http://wpftutorial.net/DataTemplates.html
  • 值轉換器(value converters): http://wpftutorial.net/ValueConverters.html
  • 綁定到多個屬性(bind to multiple properties): http://tech.pro/tutorial/809/wpf-tutorial-using-multibindings
  • 驗證數據(validating data): http://wpftutorial.net/DataValidation.html

Note7:MVVM模式之數據綁定