數據綁定基礎

WPF數據綁定爲應用程序提供了一種簡單而一致的方法來顯示數據以及與數據交互。 元素能夠以CLR對象和 XML 形式綁定到來自各種數據源的數據。 
WPF 中的數據綁定功能與傳統模型相比具有一些優勢,包括本質上支持數據綁定的各種屬性、靈活的數據 UI 表示形式,以及業務邏輯與 UI 的完全分離。

數據綁定是在應用程序 UI 與業務邏輯之間建立連接的過程。 如果綁定具有正確設置並且數據提供正確通知,則當數據更改其值時,綁定到數據的元素會自動反映更改。 數據綁定可能還意味着如果元素中數據的外部表現形式發生更改,則基礎數據可以自動更新以反映更改。 例如,如果用戶編輯 TextBox 元素中的值,則基礎數據值會自動更新以反映該更改。

1. 數據綁定基礎

1.1 數據綁定模型

完整的數據綁定模型由5部分組成:目標對象、目標屬性、數據源對象、數據源屬性和綁定對象。如下:

注意點:
  • 目標屬性必須是依賴屬性。
  • 綁定源 對象並不限於自定義 CLR 對象。 WPF 數據綁定支持 CLR 對象和 XML 形式的數據。 舉例來說,綁定源可以是 UIElement、任何列表對象、與 ADO.NET 數據或 Web 服務關聯的 CLR 對象,也可以是包含 XML 數據的 XmlNode。

1.2 數據綁定方向

數據綁定方向通過Binding 對象的 Mode 屬性來控制。
Mode包括:

成員名稱

說明

TwoWay

導致對源屬性或目標屬性的更改可自動更新對方。 此綁定類型適用於可編輯窗體或其他完全交互式 UI 方案。

OneWay

當綁定源(源)更改時,更新綁定目標(目標)屬性。 如果要綁定的控件爲隱式只讀控件,則適用此綁定類型。 例如,可以綁定到如股市代號之類的源。 或者,可能目標屬性沒有用於進行更改(例如表的數據綁定背景色)的控件接口。 如果不需要監視目標屬性的更改,則使用 OneWay 綁定模式可避免 TwoWay 綁定模式的系統開銷。

OneTime

當應用程序啓動或數據上下文更改時,更新綁定目標。 此綁定類型適用於以下情況:使用當前狀態的快照適合使用的或數據狀態實際爲靜態的數據。 如果要從源屬性初始化具有某個值的目標屬性,並且事先不知道數據上下文,則也可以使用此綁定類型。 實質上,這是 OneWay 綁定的較簡單的形式,它在不更改源值的情況下可提供更好的性能。

OneWayToSource

當目標屬性更改時更新源屬性。與OneWay相反。

Default

使用綁定目標的默認 Mode 值。 每個依賴項屬性的默認值都不同。 一般情況下,用戶可編輯控件屬性(例如文本框和複選框的屬性)默認爲雙向綁定,而多數其他屬性默認爲單向綁定。 確定依賴項屬性綁定在默認情況下是單向還是雙向的編程方法是:使用 GetMetadata 來獲取屬性的屬性元數據,然後檢查 BindsTwoWayByDefault 屬性的布爾值。也可通過MSDN查看對應依賴屬性的信息中設置爲 true 的元數據屬性。

1.3 數據綁定的觸發條件

數據綁定的觸發條件通過Binding 對象的 UpdateSourceTrigger 屬性來控制。

成員名稱

說明

Default

綁定目標屬性的默認 UpdateSourceTrigger值。多數依賴項屬性的默認值爲 PropertyChanged,而 Text屬性的默認值爲 LostFocus

確定依賴項屬性的默認 UpdateSourceTrigger值的編程方法是使用 GetMetadata來獲取屬性的屬性元數據,然後檢查 DefaultUpdateSourceTrigger屬性的值。

PropertyChanged

當綁定目標屬性更改時,立即更新綁定源。

LostFocus

當綁定目標元素失去焦點時,更新綁定源。

Explicit

僅在調用 UpdateSource方法時更新綁定源。


1.4 數據綁定實例

現在有兩個TextBox,當一個文本框內容修改的時候另外一個文本框同步修改。WinForm的思想應該是分別給兩個文本框寫文本改變事件。
將第一個文本框的Text屬性綁定到第二個文本框的Text屬性即可。
XAML中使用
Text="{Binding Path=Text,ElementName=txtBox2,Mode=Default,UpdateSourceTrigger=PropertyChanged}"
程序代碼中使用
txtBox1.SetBinding(TextBox.TextProperty, new Binding("Text")
{
	ElementName="txtBox2",
	//Mode=BindingMode.Default,
	UpdateSourceTrigger=UpdateSourceTrigger.PropertyChanged
});

1.5小結

在依賴屬性進價(一)中講到的依賴屬性元數據,這裏的綁定方向和觸發條件的Default就是在依賴屬性元數據中的。
通過下面的編程方法來獲得他們的Default值(以下爲即時窗口調試輸出結果):
TextBox.TextProperty.GetMetadata(txtBox1);
{System.Windows.FrameworkPropertyMetadata}
    [System.Windows.FrameworkPropertyMetadata]: {System.Windows.FrameworkPropertyMetadata}
    CoerceValueCallback: {Method = {System.Object CoerceText(System.Windows.DependencyObject, System.Object)}}
    DefaultValue: ""
    PropertyChangedCallback: {Method = {Void OnTextPropertyChanged(System.Windows.DependencyObject, System.Windows.DependencyPropertyChangedEventArgs)}}
(TextBox.TextProperty.GetMetadata(txtBox1) as System.Windows.FrameworkPropertyMetadata).BindsTwoWayByDefault
true
(TextBox.TextProperty.GetMetadata(txtBox1) as System.Windows.FrameworkPropertyMetadata).DefaultUpdateSourceTrigger
LostFocus

2. 綁定數據源的4種方式

  • Source
定義資源
<Window.Resources>
	<local:Student x:Key="student" id="01" name="小麗"/>
</Window.Resources>
XAML中使用
Text="{Binding Path=id,Source={StaticResource student}}"

  • ElementName
該綁定方式多用於元素間的綁定,上面的數據綁定實例中用的就是ElementName綁定。

  • RelativeSource
RelativeSourceMode枚舉
成員名稱

說明

PreviousData

允許您綁定所顯示數據項列表中以前的數據項(不是包含數據項的控件)。

TemplatedParent

引用應用了模板(其中有數據綁定元素)的元素。這類似於設置 TemplateBindingExtension,並僅當 Binding在模板中時適用。

Self

引用您對其設置綁定的元素,並允許您將該元素的一個屬性綁定到同一元素中的其他屬性。

FindAncestor

引用數據綁定元素父鏈中的上級。您可以使用它綁定到特定類型或其子類的上級。如果您要指定 AncestorType/ AncestorLevel,可以使用此模式。


  • DataContext
需要指定綁定對象或其父級的DataContext,一般可在程序代碼中指定。
this.DataContext = this;
Text="{Binding stu.id}"

3. 數據更改通知

此時,添加個button,讓stu的id值加"01"的話,TextBox中的內容沒有得到相應的更新。
雖然將數據綁定的方向規定爲OneWay或者TwoWay,但是數據源沒有一種機制通知目標,屬性發送改變後目標是得不到相應的更新的。通常解決這個問題有兩種方法。
  • 將數據源屬性實現爲依賴屬性。此法多用於元素之間,對於Person這種類型,此法不合適。
  • 數據源實現INotifyPropertyChanged接口。
INotifyPropertyChanged 接口用於向客戶端(通常是執行綁定的客戶端)發出某一屬性值已更改的通知。
public class Student : INotifyPropertyChanged
{
	private string _id;

	public string id
	{
		get { return _id; }
		set
		{
			_id = value;
			NotifyPropertyChanged("id");
		}
	}
	public string name { get; set; }
	public Sex sex{ get; set; }

	public event PropertyChangedEventHandler PropertyChanged;

	private void NotifyPropertyChanged(string info)
	{
		if (PropertyChanged != null)
		{
			PropertyChanged(this, new PropertyChangedEventArgs(info));
		}
	}
}
效果圖

4. 數據轉換器(ValueConverter)

用於不同數據類型間值的轉換。譬如將枚舉類型的Sex值轉爲中文顯示。
轉換器代碼
public class SexConverter : IValueConverter
{
	//綁定屬性-->目標屬性
	public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
	{
		string sex = "其他";
		if(value is Sex)
		{
			sex = (Sex)value == Sex.Boy ? "男" : ((Sex)value == Sex.Girl ? "女" : "其他");
		}
		return sex;
	}

	//目標屬性-->綁定屬性
	public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
	{
		return value.ToString().Trim() == "男" ? Sex.Boy : (value.ToString().Trim() == "女" ? Sex.Girl : Sex.Other);
	}
}
XMAL中代碼
<TextBox HorizontalAlignment="Left" Height="32" Margin="31,137,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="227"
	                 Text="{Binding stu.sex,Converter={StaticResource sexConverter}}"/>
效果

5.數據驗證

接受用戶輸入的大多數應用程序都需要具有驗證邏輯,以確保用戶輸入了需要的信息。 驗證檢查可以基於類型、範圍、格式或其他應用程序特定的要求。

5.1 創建驗證規則

ValidationRule 對象可檢查屬性的值是否有效。 WPF 具有以下兩種類型的內置 ValidationRule 對象:
ExceptionValidationRule 檢查在更新綁定源屬性的過程中引發的異常。 在前面的示例中,StartPrice 爲整數類型。 當用戶輸入的值無法轉換爲整數時,將引發異常,這會導致將綁定標記爲無效。 用於顯式設置 ExceptionValidationRule 的可選語法是將 Binding 或 MultiBinding 對象上的 ValidatesOnExceptions 屬性設置爲 true。
DataErrorValidationRule 對象檢查由實現 IDataErrorInfo 接口的對象所引發的錯誤。 有關使用此驗證規則的示例,請參見 DataErrorValidationRule。 用於顯式設置DataErrorValidationRule 的可選語法是將 Binding 或 MultiBinding 對象上的 ValidatesOnDataErrors 屬性設置爲 true。

5.1.1 自定義驗證規則

可以通過從 ValidationRule 類派生和實現 Validate 方法來創建自己的驗證規則。
class IdRule : ValidationRule
{
	public override ValidationResult Validate(object value, CultureInfo cultureInfo)
	{
		if(string.IsNullOrWhiteSpace(value.ToString()))
		{
			return new ValidationResult(false, "代碼不能爲。");
		}
		else
		{
			Regex regex = new Regex(@"^\d+$");
			if(regex.IsMatch(value.ToString()))
			{
				return ValidationResult.ValidResult;
			}
			else
			{
				return new ValidationResult(false, "代碼只能輸入數字。");
			}
		}
	}
}
XAML中使用
<TextBox HorizontalAlignment="Left" Height="29" Margin="124,216,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="247">
	<TextBox.Text>
		<Binding Path="stu.id">
			<Binding.ValidationRules>
				<local:IdRule />
			</Binding.ValidationRules>
		</Binding>
	</TextBox.Text>
</TextBox>

5.2驗證提示方法

5.2.1使用附加屬性Validation.ErrorTemplate

<ControlTemplate x:Key="validationTemplate">
	<DockPanel>
		<TextBlock Foreground="Red" FontSize="20">!</TextBlock>
		<AdornedElementPlaceholder/>
	</DockPanel>
</ControlTemplate>

5.2.2使用ToolTip

<Style x:Key="textStyleTextBox" TargetType="TextBox">
	<Style.Triggers>
		<Trigger Property="Validation.HasError" Value="true">
			<Setter Property="ToolTip"
					Value="{Binding RelativeSource={RelativeSource Self},
						Path=(Validation.Errors)[0].ErrorContent}"/>
		</Trigger>
	</Style.Triggers>
</Style>
驗證的TextBoxXAML代碼
<TextBox HorizontalAlignment="Left" Height="29" Margin="124,216,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="247"
		 Validation.ErrorTemplate="{StaticResource validationTemplate}"
		 Style="{StaticResource textStyleTextBox}">
	<TextBox.Text>
		<Binding Path="stu.id">
			<Binding.ValidationRules>
				<local:IdRule />
			</Binding.ValidationRules>
		</Binding>
	</TextBox.Text>
</TextBox>
效果



作者:FoolRabbit
出處:http://blog.csdn.net/rabbitsoft_1987
歡迎任何形式的轉載,未經作者同意,請保留此段聲明!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章