WPF数据绑定(1-简单数据绑定)
2019獨角獸企業重金招聘Python工程師標準>>>
附WPF書籍推薦:
1、不要為書籍經銷商的炒作蒙蔽,國內翻譯的《WPF揭秘》被褒揚成經典,其實我認為該書淺嘗則止,不夠詳盡是其最致命的弱點
2、《WPF程序設計指南App=Code+markup》是本好書,仔細研讀還能學到很多開發技巧,但書籍將code與markup獨立開有失,如果能
將其結合起來并內容章節仔細組織將會更受歡迎。
3、《Pro WPF in C# 2008 Windows Presentation Foundation with .NET 3.5 SECOND EDITION》是本好書,
我認為和《OReilly.Programming.WPF.2nd.Edition.Aug.2007》不分伯仲,兩本書對WPF內容都解釋十分詳盡,章節設置也十分合理
適合快速掌握WPF開發知識,是學習WPF的首選。
4、至于其他書籍各位仁者見仁,智者見智,至于書店里某本國產WPF編程書籍,我不想多言,只是我建議改名為《簡單了解WPF》也許更合理。
5、書有千種,各有特色,計算機編程開發書籍國產書籍有精品但不多,對新出現的技術如果沒有在市場上使用3年,還是建議首選國外書籍,
?? 希望我這句話不要讓有些人不高興,事實如此,要反駁的話請象李小龍一樣站出來,打出一套好拳給大家看看。
?
//************************************************************
?
數據綁定就是將各種數據與用戶展現控件進行關聯的過程。WPF的數據綁定機制可以以最少的代碼方便地處理這樣的關聯。
簡單數據綁定
1 無數據綁定
在實現這樣的用戶交互的時候:
?
在沒有任何數據綁定機制實現的時候無非采用
this.nameTextBox.Text = person.Name;
this.ageTextBox.Text = person.Age.ToString();
這樣的賦值的方法,而一旦數據改變了,將界面的值寫回給person對象。
1.1對象改變
我們現在需要當對象發生改變的時候,UI的現實如何同步跟著改變呢?
實現起來還是比較復雜的,看如下代碼就明白了。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;//INotifyPropertyChanged
namespace SimpleDataBinding
{
??? class Person:INotifyPropertyChanged
??? {
??????? public event PropertyChangedEventHandler PropertyChanged;
??????? protected void Notify(string PropName)
??????? {
??????????? if (this.PropertyChanged != null)
??????????? {
??????????????? PropertyChanged(this,new PropertyChangedEventArgs(PropName));
??????????? }
??????? }
??????? public Person()
??????? {
??????????? _Age = 0;
??????????? _name = "Null";
??????? }
??????? private string _name;
??????? public string Name
??????? {
??????????? get
??????????? {? return _name; }
??????????? set
??????????? {
??????????????? if (value == _name)
??????????????? { return; }
??????????????? _name = value;//注意:不能用this.Name來賦值,如果這樣形成循環調用,棧溢出
??????????????? Notify("Name");
??????????? }
??????? }
??????? private int _Age;
??????? public? int Age
??????? {
??????????? get
??????????? { return _Age; }
??????????? set
??????????? {
??????????????? if (value == _Age) return;
??????????????? _Age = value;
??????????????? Notify("Age");
??????????? }
??????? }
??? }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
namespace SimpleDataBinding
{
??? /// <summary>
??? /// Window1.xaml 的交互邏輯
??? /// </summary>
??? public partial class WithoutDataBinding : Window
??? {
??????? private Person _person;
??????? public WithoutDataBinding()
??????? {
??????????? InitializeComponent();
??????????? //可以采用如下對象初始化,但本示例為了使用使用屬性改變UI改變就先不賦值。
??????????? //_person = new Person
??????????? //{
??????????? //??? Name = "zhangying",
??????????? //??? Age = 28
??????????? //};
??????????? _person = new Person();
??????????? _person.PropertyChanged += delegate(object sender, PropertyChangedEventArgs e)
?????????? {
?????????????? switch (e.PropertyName)
?????????????? {
?????????????????? case "Name":
?????????????????????? this.txt_name.Text = _person.Name;
?????????????????????? break;
?????????????????? case "Age":
?????????????????????? this.txt_age.Text = _person.Age.ToString();
?????????????????????? break;
?????????????? }
?????????? };
??????? }
??????? private void button2_Click(object sender, RoutedEventArgs e)
??????? {
??????????? _person.Name = "zhangying";
??????????? _person.Age = 28;
??????? }
??? }
}
1.2 UI改變
當UI的輸入值發生變化的時候,如何同步對象的值呢?這需要給他們設置事件代碼:
private void txt_name_TextChanged(object sender, TextChangedEventArgs e)
{
_person.Name = this.txt_name.Text;
}
private void txt_age_TextChanged(object sender, TextChangedEventArgs e)
{
int age = 0;
if(int.TryParse(this.txt_age.Text,out age)
{
_person.Age = age ;
}
}
2數據綁定
上面的示例是使用人工的手段將對象屬性與UI顯示進行同步,而WPF數據綁定則是注冊兩個屬性與數據綁定引擎,來處理同步,合適的數據轉換,如下圖:
2.1 Bindings
1.使用元素屬性綁定:
<TextBox>
<TextBox.Text>
<Binding Path="Age" />
</TextBox.Text>
</TextBox>
2. 簡化屬性綁定
<TextBox Text="{Binding Path=Age}" />
更簡化方式:
<TextBox Text="{Binding Age}" />
看一個更多特性的綁定方式(屬性元素的方式):
<TextBox>
<TextBox.Foreground>
<Binding Path="Age" Mode="OneWay" Source="{StaticResource Tom}"
Converter="{StaticResource ageConverter}" />
</TextBox.Foreground>
</TextBox>
上面的綁定可以采用如下簡潔方式:
Foreground="{Binding Path=Age, Mode=OneWay, Source={StaticResource Tom},
Converter={StaticResource ageConverter}}" />
注意上面的引號的用法和不用引號的用法,使用屬性元素的方式必須用引號。
下面圖表列出綁定到一個對象時候可能用到的屬性:
這些屬性后面將一一介紹到。
2.2 隱式數據源Implicit Data Source
在WPF中,每個FrameworkElement 和FrameworkContentElement對象都有一個DataContex屬性,該屬性是Object類型,所以你可以給它指定任何類型的值。當我們定義個對象作為綁定對象,則綁定引擎在邏輯樹上尋找該數據庫綁定源,如下圖所示:
2.3 數據島Data Islands
看以下代碼示例就明白了:
private void btn_Click(object sender, RoutedEventArgs e)
{
Person person = (Person)this.FindResource("zy");
MessageBox.Show(string.Format("I am {0},Age is {1}",person.Name,person.Age.ToString()));
}
2.4 顯示數據源Explicit Data Source
顯示數據源設置對于多個數據源是很重要的,我們可以通過綁定屬性的Source來實現。
注意上面兩個文本框設置了不同的數據源的屬性。
2.5 綁定到其他控件binding to other controls
如下代碼所示:
<Grid>
<Slider Name="slider1" />
<TextBlock Text="{Binding Path=Value,ElementName=slider1}"/>
</Grid>
2.6 值轉換 Value Conversation
上面的代碼我們發現綁定是將一個數值類型綁定到一個字符串,類型不符合,這究竟是如何做到的呢?原來這是一個號稱Value Converter類的功勞,它實現了IValueConverter接口,該接口有兩個方法:Convert和ConvertBack。(該接口在System.Windows.Data命名空間,PresentationFramework.dll程序集中),實現 IValueConverter 接口時,最好用ValueConversionAttribute 屬性來修飾此實現,以便向開發工具指示轉換所涉及的數據類型,如下面的示例所示:(以下示例摘錄自MSDN)
看下面的使用方法:
使用方法,先指定數據源
2.7 Editable Value Conversion
2.8 Validation
一個驗證規則就是在一條目標數據更新來源數據的時候的一段數據驗證代碼,這段代碼一般是繼承ValidationRule類并覆蓋Validate方法,一個內置的規則稱為ExceptionValidationRule
如下代碼我們可以看到使用最基本的驗證的方式:
當我們運行程序的時候
紅色邊框顯示輸入框數據格式錯誤。但是我們發現這樣仍然不夠友好,因為沒有消息提示到底為什么錯誤。
為了顯示錯誤,需要使用綁定的事件來偵聽ValidationError,代碼示例很容易說明這點:
這樣還不行,還必須如下圖設置:
運行結果大家肯定很明白了,當然這也許還不是我們需要的,我們可以更多地控制行為,這就要求我們自定義驗證規則。下面我們以一個實例來講解自定義驗證規則。
首先我們通過繼承ValidationRule類然后覆寫validate方法,還是讓代碼說明一切吧:
在實際項目中,可能大家對錯誤提示采用對話框不是很喜歡,最好的方式是WindowsForm的驗證方式Tooltip,但有一點需要注意ValidateRule沒有類似ValidateSucess事件讓我們清除錯誤的時候產生的Tooltip,以至于整個Tooltip的顯示很奇怪。
2.9綁定路徑句法Binding Path Syntax
以下列出MSDN上的描述:
使用 Path 屬性可以指定您要綁定到的源值:
· 在最簡單的情況下,Path 屬性值是要用于綁定的源對象的屬性名,如 Path=PropertyName。
· 在 C# 中可以通過類似語法指定屬性的子屬性。 例如,子句 Path=ShoppingCart.Order 設置與對象或屬性 ShoppingCart 的 Order 子屬性的綁定。
· 若要綁定到附加屬性,應在附加屬性周圍放置圓括號。 例如,若要綁定到附加屬性 DockPanel..::.Dock,則語法是 Path=(DockPanel.Dock)。
· 可以在要應用索引器的屬性名后面的方括號內指定屬性的索引器。 例如,子句 Path=ShoppingCart[0] 將綁定設置為與屬性的內部索引處理文本字符串“0”的方式對應的索引。 還支持嵌套的索引器。
· 可以在 Path 子句中混合索引器和子屬性;例如,Path=ShoppingCart.ShippingInfo[MailingAddress,Street].
· 在索引器內部,您可以有多個由逗號 (,) 分隔的索引器參數。 可以使用圓括號指定每個參數的類型。 例如,您可以有 Path="[(sys:Int32)42,(sys:Int32)24]",其中 sys 映射到 System 命名空間。
· 如果源為集合視圖,則可以用斜杠 (/) 指定當前項。 例如,子句 Path=/ 用于設置到視圖中當前項的綁定。 如果源為集合,則此語法指定默認集合視圖的當前項。
· 可以結合使用屬性名和斜杠來遍歷作為集合的屬性。 例如,Path=/Offices/ManagerName 指定源集合的當前項,該源集合包含也作為集合的 Offices 屬性。 其當前項是一個包含 ManagerName 屬性的對象。
· 也可以使用句點 (.) 路徑綁定到當前源。例如,Text=”{Binding}” 等效于 Text=”{Binding Path=.}”。
轉義機制
· 在索引器 ([ ]) 內部,插入符號 (^) 用于對下一個字符進行轉義。
· 如果您在 XAML 中設置 Path,則還需要使用 XAML 實體對 XAML 分析程序專用的某些字符進行轉義:
· 使用 & 對字符“&”進行轉義。
· 使用 > 對結束標記“>”進行轉義。
· 此外,如果您使用標記擴展語法描述屬性中的整個綁定,則需要使用反斜杠 \ 對 WPF 標記擴展分析程序專用的字符進行轉義:
· 反斜杠 \ 本身是轉義字符。
· 等號 (=) 將屬性名與屬性值隔開。
· 逗號 (,) 用于分隔屬性。
· 右大括號 (}) 是標記擴展的結尾。
Binding the ToolTip property to the validation error message
<TextBox
Name="ageTextBox" ...
ToolTip="{Binding
ElementName=ageTextBox,
Path=(Validation.Errors)[0].ErrorContent}">
<TextBox.Text>
<Binding Path="Age">
<!-- No need for NotifyOnValidationError="true" -->
<Binding.ValidationRules>
<local:NumberRangeRule Min="0" Max="128" />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
2.10相對數據源Relative Source
還是代碼來說明更易理解
<TextBox ...
ToolTip="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}">
在上面實例中我們采用 ElementName=txtDate這樣的方式指定的,這里使用self來表示引用該標簽所在的元素生成的對象,當然我們還可以使用類似于parent指向上一級,關于Relative resource在后續章節會繼續討論。
2.11更新源數據觸發器Update Source Trigger
在前面我們基本上是在目標控件的失去焦點的時候發生相關驗證并更新數據源的,而實際上更新數據源的機制有多種類型,如下:
namespace System.Windows.Data
{
???? public enum UpdateSourceTrigger
???? {
????????? Default = 0, // updates "naturally" based on the target control
????????? PropertyChanged = 1, // updates the source immediately
????????? LostFocus = 2, // updates the source when focus changes
????????? Explicit = 3, // must call BindingExpression.UpdateSource()
????? }
}
而在XAML里面必須如下聲明:
<Binding Path="Age" UpdateSourceTrigger="PropertyChanged">
轉載于:https://my.oschina.net/pangzhuzhu/blog/318047
總結
以上是生活随笔為你收集整理的WPF数据绑定(1-简单数据绑定)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: win8桌面壁纸路径
- 下一篇: java.lang.Instantiat