WPF 中的數據綁定功能與傳統模型相比具有一些優勢,包括本質上支持數據綁定的各種屬性、靈活的數據 UI 表示形式,以及業務邏輯與 UI 的完全分離。
數據綁定是在應用程序 UI 與業務邏輯之間建立連接的過程。 如果綁定具有正確設置並且數據提供正確通知,則當數據更改其值時,綁定到數據的元素會自動反映更改。 數據綁定可能還意味着如果元素中數據的外部表現形式發生更改,則基礎數據可以自動更新以反映更改。 例如,如果用戶編輯 TextBox 元素中的值,則基礎數據值會自動更新以反映該更改。
1. 數據綁定基礎
1.1 數據綁定模型
- 目標屬性必須是依賴屬性。
- 綁定源 對象並不限於自定義 CLR 對象。 WPF 數據綁定支持 CLR 對象和 XML 形式的數據。 舉例來說,綁定源可以是 UIElement、任何列表對象、與 ADO.NET 數據或 Web 服務關聯的 CLR 對象,也可以是包含 XML 數據的 XmlNode。
1.2 數據綁定方向
Mode包括:
成員名稱 |
說明 |
TwoWay |
導致對源屬性或目標屬性的更改可自動更新對方。 此綁定類型適用於可編輯窗體或其他完全交互式 UI 方案。 |
OneWay |
當綁定源(源)更改時,更新綁定目標(目標)屬性。 如果要綁定的控件爲隱式只讀控件,則適用此綁定類型。 例如,可以綁定到如股市代號之類的源。 或者,可能目標屬性沒有用於進行更改(例如表的數據綁定背景色)的控件接口。 如果不需要監視目標屬性的更改,則使用 OneWay 綁定模式可避免 TwoWay 綁定模式的系統開銷。 |
OneTime |
當應用程序啓動或數據上下文更改時,更新綁定目標。 此綁定類型適用於以下情況:使用當前狀態的快照適合使用的或數據狀態實際爲靜態的數據。 如果要從源屬性初始化具有某個值的目標屬性,並且事先不知道數據上下文,則也可以使用此綁定類型。 實質上,這是 OneWay 綁定的較簡單的形式,它在不更改源值的情況下可提供更好的性能。 |
OneWayToSource |
當目標屬性更改時更新源屬性。與OneWay相反。 |
Default |
使用綁定目標的默認 Mode 值。 每個依賴項屬性的默認值都不同。 一般情況下,用戶可編輯控件屬性(例如文本框和複選框的屬性)默認爲雙向綁定,而多數其他屬性默認爲單向綁定。 確定依賴項屬性綁定在默認情況下是單向還是雙向的編程方法是:使用 GetMetadata 來獲取屬性的屬性元數據,然後檢查 BindsTwoWayByDefault 屬性的布爾值。也可通過MSDN查看對應依賴屬性的信息中設置爲 true 的元數據屬性。 |
1.3 數據綁定的觸發條件
成員名稱 |
說明 |
Default |
綁定目標屬性的默認 UpdateSourceTrigger值。多數依賴項屬性的默認值爲 PropertyChanged,而 Text屬性的默認值爲 LostFocus。 確定依賴項屬性的默認 UpdateSourceTrigger值的編程方法是使用 GetMetadata來獲取屬性的屬性元數據,然後檢查 DefaultUpdateSourceTrigger屬性的值。 |
PropertyChanged |
當綁定目標屬性更改時,立即更新綁定源。 |
LostFocus |
當綁定目標元素失去焦點時,更新綁定源。 |
Explicit |
僅在調用 UpdateSource方法時更新綁定源。 |
1.4 數據綁定實例
將第一個文本框的Text屬性綁定到第二個文本框的Text屬性即可。
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值(以下爲即時窗口調試輸出結果):
{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>
Text="{Binding Path=id,Source={StaticResource student}}"
- ElementName
- RelativeSource
成員名稱 |
說明 |
PreviousData |
允許您綁定所顯示數據項列表中以前的數據項(不是包含數據項的控件)。 |
TemplatedParent |
引用應用了模板(其中有數據綁定元素)的元素。這類似於設置 TemplateBindingExtension,並僅當 Binding在模板中時適用。 |
Self |
引用您對其設置綁定的元素,並允許您將該元素的一個屬性綁定到同一元素中的其他屬性。 |
FindAncestor |
引用數據綁定元素父鏈中的上級。您可以使用它綁定到特定類型或其子類的上級。如果您要指定 AncestorType和/或 AncestorLevel,可以使用此模式。 |
- DataContext
this.DataContext = this;
Text="{Binding stu.id}"
3. 數據更改通知
雖然將數據綁定的方向規定爲OneWay或者TwoWay,但是數據源沒有一種機制通知目標,屬性發送改變後目標是得不到相應的更新的。通常解決這個問題有兩種方法。
- 將數據源屬性實現爲依賴屬性。此法多用於元素之間,對於Person這種類型,此法不合適。
- 數據源實現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)
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);
}
}
<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>
驗證的TextBox的XAML代碼<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
歡迎任何形式的轉載,未經作者同意,請保留此段聲明!