WPF資料繫結 Binding
目錄
簡介
這是一篇記錄筆者閱讀學習劉鐵猛老師的《深入淺出WPF》的讀書筆記,如果文中內容閱讀不暢,推薦購買正版書籍詳細閱讀。
本文引用了大量官方文件,如需詳細瞭解請自行查閱MSDN。
什麼是資料繫結?
資料繫結是在應用 UI 與其顯示的資料之間建立連線的過程,是一座連線應用UI與其顯示的資料之間的橋樑。
“一橋飛架南北,天塹變通途”,我們可以想象Binding這座橋樑上鋪設了高速公路,我們不但可以控制公路是在源與目標之間雙向同行還是某個方向的單行道,還可以控制對資料放行的事件,甚至可以在橋上假設一些“關卡”用來轉換資料型別或者校驗資料的正確性。
如果把Binding比作資料的橋樑,那麼它的兩端分別是Binding的源(Source)和目標(Target)。資料從哪裡來哪裡就是源,Bindng是架在中間的橋樑,Binding目標是資料要往哪兒去(所以我們就要把橋架向哪裡)。一般情況下,Binding源是邏輯層的物件,Binding目標是UI層的控制元件物件,這樣,資料就會源源不斷通過Binding送達UI層、被UI層展現,也就完成了資料驅動UI的過程。
資料繫結基本概念
不論要繫結什麼元素,也不論資料來源是什麼性質,每個繫結都始終遵循下圖所示的模型。
如圖所示,資料繫結實質上是繫結目標與繫結源之間的橋樑。 該圖演示了以下基本的 WPF 資料繫結概念:
-
通常情況下,每個繫結具有四個元件:
- 繫結目標物件。
- 目標屬性。
- 繫結源。
- 指向繫結源中要使用的值的路徑。
例如,如果要將
TextBox
的內容繫結到Employee.Name
屬性,則目標物件是TextBox
,目標屬性是 Text 屬性,要使用的值是 Name,源物件是 Employee 物件。 -
目標屬性必須為依賴屬性。 大多數 UIElement 屬性都是依賴屬性,而大多數依賴屬性(只讀屬性除外)預設支援資料繫結。 (僅派生自
DependencyObject
。) -
儘管未在圖中顯示,但請注意,繫結源物件不限於自定義 .NET 物件。 WPF 資料繫結支援 .NET 物件和 XML 形式的資料。 例如,繫結源可以是 UIElement、任何列表物件、ADO.NET 或 Web 服務物件,或包含 XML 資料的 XmlNode。 有關詳細資訊,請參閱繫結源概述。
請務必記住,在建立繫結時,需要將繫結目標繫結到繫結源。 例如,如果要使用資料繫結在 ListBox 中顯示一些基礎 XML 資料,則需要將 ListBox
繫結到 XML 資料。
若要建立繫結,請使用 Binding 物件。
控制Binding的方向及資料更新
Binding的常用屬性
屬性 | 說明 |
---|---|
Converter | 轉換器 |
ElementName | 繫結的源物件 |
Fallback Value | 繫結無法返回有效值時的預設顯示 |
Mode | 繫結方式 |
Path | 路徑 |
RelativeSource | 常用於自身繫結或者資料模板中指定繫結的源物件 |
Source | 源物件 |
StringFormat | 格式化表示式 |
UpdateSourceTrigger | 在繫結將發生的物件上設定事件 |
ValidationRules | 驗證規則 |
控制Binding資料流的方向-Mode
“一橋飛架南北,天塹變通途”,我們可以想象Binding這座橋樑上鋪設了高速公路,我們不但可以控制公路是在源與目標之間雙向同行還是某個方向的單行道,還可以控制對資料放行的事件,甚至可以在橋上假設一些“關卡”用來轉換資料型別或者校驗資料的正確性。
此圖演示了不同型別的資料流:
- 通過 OneWay 繫結,對源屬性的更改會自動更新目標屬性,但對目標屬性的更改不會傳播回源屬性。 如果繫結的控制元件為隱式只讀,則此型別的繫結適用。 例如,可能會繫結到股票行情自動收錄器這樣的源,也可能目標屬性沒有用於進行更改的控制元件介面(例如表的資料繫結背景色)。 如果無需監視目標屬性的更改,則使用 OneWay 繫結模式可避免 TwoWay 繫結模式的系統開銷。
- 通過 TwoWay 繫結,更改源屬性或目標屬性時會自動更新另一方。 此型別的繫結適用於可編輯窗體或其他完全互動式 UI 方案。 大多數屬性預設為 OneWay 繫結,但某些依賴屬性(通常為使用者可編輯控制元件的屬性,例如 TextBox.Text 和 CheckBox.IsChecked)預設為 TwoWay 繫結。 用於確定依賴屬性繫結在預設情況下是單向還是雙向的程式設計方法是:使用 DependencyProperty.GetMetadata 獲取屬性元資料,然後檢查 FrameworkPropertyMetadata.BindsTwoWayByDefault 屬性的布林值。
- OneWayToSource 繫結與 OneWay 繫結相反;當目標屬性更改時,它會更新源屬性。 一個示例方案是隻需要從 UI 重新計算源值的情況。
- OneTime 該繫結會使源屬性初始化目標屬性,但不傳播後續更改。 如果資料上下文發生更改,或者資料上下文中的物件發生更改,則更改不會在目標屬性中反映。 如果適合使用當前狀態的快照或資料實際為靜態資料,則此型別的繫結適合。 如果你想使用源屬性中的某個值來初始化目標屬性,且提前不知道資料上下文,則此型別的繫結也有用。 此模式實質上是 OneWay 繫結的一種簡化形式,它在源值不更改的情況下提供更好的效能。
若要檢測源更改(適用於 OneWay 和 TwoWay 繫結),則源必須實現合適的屬性更改通知機制,例如 INotifyPropertyChanged。 請參閱如何:實現屬性更改通知,獲取 INotifyPropertyChanged 實現的示例。
觸發源更新的因素-UpdateSourceTrigger
“一橋飛架南北,天塹變通途”,我們可以想象Binding這座橋樑上鋪設了高速公路,我們不但可以控制公路是在源與目標之間雙向同行還是某個方向的單行道,還可以控制對資料放行的事件,甚至可以在橋上假設一些“關卡”用來轉換資料型別或者校驗資料的正確性。
TwoWay 或 OneWayToSource 繫結偵聽目標屬性中的更改,並將更改傳播回源(稱為更新源)。 例如,可以編輯文字框的文字以更改基礎源值。
但是,在編輯文字時或完成文字編輯後控制元件失去焦點時,源值是否會更新? Binding.UpdateSourceTrigger 屬性確定觸發源更新的因素。 下圖中右箭頭的點說明了 Binding.UpdateSourceTrigger 屬性的角色。
如果 UpdateSourceTrigger
值為 UpdateSourceTrigger.PropertyChanged,則目標屬性更改後,TwoWay 或 OneWayToSource 繫結的右箭頭指向的值會立即更新。 但是,如果 UpdateSourceTrigger
值為 LostFocus,則僅當目標屬性失去焦點時才會使用新值更新該值。
與 Mode 屬性類似,不同的依賴屬性具有不同的預設 UpdateSourceTrigger 值。 大多數依賴屬性的預設值為 PropertyChanged,而 TextBox.Text
屬性的預設值為 LostFocus。 PropertyChanged
表示源更新通常在每次目標屬性更改時發生。 即時更改適用於 CheckBox 和其他簡單控制元件。 但對於文字欄位,每次擊鍵後都進行更新會降低效能,使用者也沒有機會在提交新值之前使用 Backspace 鍵修改鍵入錯誤。
UpdateSourceTrigger的取值:
UpdateSourceTrigger值 | 源值何時進行更新 |
---|---|
LostFocus(預設) | 當Text控制元件拾取焦點時 |
PropertyChanged | 當鍵入到TextBox時 |
Explicit | 當應用程式呼叫UpdateSource時 |
Binding對資料的轉換與校驗
“一橋飛架南北,天塹變通途”,我們可以想象Binding這座橋樑上鋪設了高速公路,我們不但可以控制公路是在源與目標之間雙向同行還是某個方向的單行道,還可以控制對資料放行的事件,甚至可以在橋上假設一些“關卡”用來轉換資料型別或者校驗資料的正確性。
資料轉換-Converter
在建立繫結部分中,該按鈕為紅色,因為其 Background 屬性繫結到值為“Red”的字串屬性。 此字串值有效是因為 Brush 型別中存在型別轉換器,可用於將字串值轉換為 Brush。
將此資訊新增到建立繫結部分的關係圖中,使其如下所示。
但是,如果繫結源物件擁有的不是字串型別的屬性,而是 Color 型別的 Color 屬性,該怎麼辦? 在這種情況下,為了使繫結正常工作,首先需要將 Color 屬性值轉換為 Background 屬性可接受的值。 需要通過實現 IValueConverter 介面來建立一個自定義轉換器,如以下示例所示。
C#複製
[ValueConversion(typeof(Color), typeof(SolidColorBrush))]
public class ColorBrushConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Color color = (Color)value;
return new SolidColorBrush(color);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
有關更多資訊,請參見IValueConverter。
現在,使用的是自定義轉換器而不是預設轉換,關係圖如下所示。
重申一下,由於要繫結到的型別中提供了型別轉換器,因此可以使用預設轉換。 此行為取決於目標中可用的型別轉換器。 如果無法確定,請建立自己的轉換器。
資料校驗-ValidationRules
接受使用者輸入的大多數應用都需要具有驗證邏輯,以確保使用者輸入了預期資訊。 可基於型別、範圍、格式或特定於應用的其他要求執行驗證檢查。WPF 資料繫結模型允許將 ValidationRules 與 Binding 物件關聯。
ValidationRule 物件檢查屬性的值是否有效。 WPF 有兩種型別的內建 ValidationRule 物件:
- ExceptionValidationRule 檢查在繫結源屬性更新期間引發的異常。 在以上示例中,
StartPrice
為整數型別。 當用戶輸入的值無法轉換為整數時,將引發異常,這會導致將繫結標記為無效。 用於顯式設定 ExceptionValidationRule 的替代語法是在 Binding 或 MultiBinding 物件上將 ValidatesOnExceptions 屬性設定為true
。 - DataErrorValidationRule 物件檢查實現 IDataErrorInfo 介面的物件所引發的錯誤。 有關使用此驗證規則的示例,請參閱 DataErrorValidationRule。 用於顯式設定 DataErrorValidationRule 的替代語法是在 Binding 或 MultiBinding 物件上將 ValidatesOnDataErrors 屬性設定為
true
。
還可以通過從 ValidationRule 類派生並實現 Validate 方法來建立自己的驗證規則
除錯機制
可以在與繫結相關的物件上設定附加屬性 TraceLevel,以接收有關特定繫結狀態的資訊。