日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > asp.net >内容正文

asp.net

《深入浅出WPF》笔记——绑定篇(一)

發(fā)布時(shí)間:2023/12/1 asp.net 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《深入浅出WPF》笔记——绑定篇(一) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

  上一節(jié),有記錄寫(xiě)到:在WPF里,數(shù)據(jù)驅(qū)動(dòng)UI,數(shù)據(jù)占核心地位,UI次之。怎么恢復(fù)數(shù)據(jù)的核心地位,那就要先了解一下Binding。

一、Binding 基礎(chǔ)

1.1WPF中Data Binding的帶來(lái)的方便

  在設(shè)計(jì)架構(gòu)的時(shí)間,大家都很重視分層,為什么分層呢,其實(shí)分層就是為了更好的復(fù)用共同的類(lèi)庫(kù)、更好的分工,以便更好的施工。。。,無(wú)論是為什么,就算它是一種時(shí)尚吧。為了追逐它,先記錄一下一般程序的層次:數(shù)據(jù)層,邏輯處理層,表現(xiàn)層。具體的每一個(gè)層可以再去細(xì)分。很多時(shí)間對(duì)于邏輯處理層和表現(xiàn)層經(jīng)常混成一片,最終成了邯鄲學(xué)步。在WPF中,如果綁定用的好的話(huà),這種不好的結(jié)果將會(huì)很簡(jiǎn)單的避免。具體是怎么樣避免的呢?讓我們先總體的把握一下Binding。為了更好的理解Binding,讓我們先舉個(gè)例子,Binding就像一條河流,可以用來(lái)劃分界限,又能作為通往兩個(gè)地方的必經(jīng)之路。翻譯過(guò)來(lái)就是Binding是邏輯層和UI的分界線(xiàn),當(dāng)邏輯層處理了的數(shù)據(jù),通過(guò)Binding界面能很快能感應(yīng)得到,如果界面上的數(shù)據(jù)發(fā)生了變化,Binding會(huì)通知邏輯層做出相應(yīng)的操作。(關(guān)于這一段,我只能弱弱的說(shuō),感覺(jué)不是特別的官方,因?yàn)閷?duì)分層的理解我還處于菜鳥(niǎo)級(jí)的水平,希望大家狂噴啊,讓我能成長(zhǎng)的更快)。

1.2 Binding基礎(chǔ)  

  我們可以把Binding比喻成一座數(shù)據(jù)橋梁,當(dāng)一輛汽車(chē)要經(jīng)過(guò)橋的話(huà),就需要指明出發(fā)地-源(Source)和目的地-目標(biāo)(Target),數(shù)據(jù)的從哪里來(lái)是源,到哪里去是Target,一般情況下,Binding源是邏輯層的對(duì)象,目標(biāo)是UI層的控件對(duì)象。這樣數(shù)據(jù)不斷的通過(guò)Binding送達(dá)UI層,被UI層所展示也就完成了數(shù)據(jù)驅(qū)動(dòng)UI的過(guò)程。我們可以想象在Binding這座橋上鋪了高速公路,不僅可以設(shè)置其方向是否是單向,還可以為雙向的,不僅如此,在雙向綁定的時(shí)間甚至可以設(shè)置一些"關(guān)卡",用來(lái)轉(zhuǎn)化數(shù)據(jù)類(lèi)型或者是檢查數(shù)據(jù)的正確性。說(shuō)了這么多,我想用一個(gè)例子,能更好的理解Binding。需求是:通過(guò)Binding,每次按一下按鈕為文本框的Age加1.具體的代碼說(shuō)明在注釋里面已經(jīng)寫(xiě)明了。下面直接上代碼:

Person.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel;namespace Chapter_04 {class Person : INotifyPropertyChanged{//INotifyPropertyChanged向客戶(hù)端發(fā)出某一屬性值已更改的通知。public event PropertyChangedEventHandler PropertyChanged;private int age;public int Age{get { return age; }set{age = value;if (this.PropertyChanged != null){this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Age"));// 通知Binding是“Age”這個(gè)屬性的值改變了 }}}} } XAML <Window x:Class="Chapter_04.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="MainWindow" Height="230" Width="250"><Grid Background="Azure"><TextBlock Height="23" HorizontalAlignment="Left" Margin="12,39,0,0" Name="textBlock1" Text="年齡:" VerticalAlignment="Top" Width="44" /><TextBox Height="23" HorizontalAlignment="Left" Margin="62,36,0,0" x:Name="txtAge" VerticalAlignment="Top" Width="120" Text="22" /><Button Content="年齡加1" Height="23" HorizontalAlignment="Left" Margin="107,114,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" /></Grid> </Window> cs 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;namespace Chapter_04 {/// <summary>/// MainWindow.xaml 的交互邏輯/// </summary>public partial class MainWindow : Window{Person p;public MainWindow(){InitializeComponent();//定義一個(gè)人的實(shí)例對(duì)象,并設(shè)置其初始值為文本框的值;p = new Person();p.Age = Convert.ToInt32(txtAge.Text);//準(zhǔn)備binding 設(shè)置其源為剛剛創(chuàng)建的對(duì)象,并指定其訪(fǎng)問(wèn)路徑為對(duì)象的Age字段,// Binding binding = new Binding();binding.Source = p;binding.Path = new PropertyPath("Age");//將數(shù)據(jù)源與目標(biāo)連接在一起---其中把txtAge設(shè)置為綁定目標(biāo),并指定目標(biāo)的屬性為 //靜態(tài)只讀DependencyProperty類(lèi)型的依賴(lài)屬性TextBox.TextProperty.(運(yùn)行是可以賦值的,注意與const的區(qū)別)//這類(lèi)屬性的值可以通過(guò)binding依賴(lài)在其他對(duì)象的屬性值上,被其他隊(duì)形的屬性值所驅(qū)動(dòng)。BindingOperations.SetBinding(this.txtAge, TextBox.TextProperty, binding);}private void button1_Click(object sender, RoutedEventArgs e){p.Age += 1;}} }

其中Cs的代碼可以把InitializeComponent();后面的代碼去掉,一句就搞定的

this.txtAge.SetBinding(TextBox.TextProperty, new Binding("Age") {Source= p=new Person(){Age=Convert.ToInt32(txtAge.Text)}});

最后的效果圖為圖1,并且點(diǎn)擊按鈕年齡加1:

圖1

這個(gè)不是跟以前的winform差不多嗎?初看差不多,但是這里讓年齡加1的是對(duì)象的屬性,而不是平時(shí)用的txtAge+=1。這樣做有個(gè)明顯得好處是,如果兩個(gè)文本框都綁定的p.Age,那么點(diǎn)擊下按鈕,兩個(gè)文本框都會(huì)加1.在這里源是p對(duì)象(沒(méi)有使用邏輯層),目標(biāo)是txtAge控件。是不是對(duì)Binding有點(diǎn)感覺(jué)了。接下來(lái)介紹Binding的路徑(Path)和源(Source)。

?二、Binding的路徑和源

2.1把控件作為Binding的源與Binding標(biāo)記擴(kuò)展的完美結(jié)合

  除了邏輯層對(duì)象可以作為Binding的源外,控件也可以作為Binding的源,這樣是不僅能使UI元素產(chǎn)生聯(lián)動(dòng)的效果,也會(huì)使Binding在控件間建立關(guān)聯(lián)。下面給出一個(gè)TextBox的值隨著Slider的值得變化而變化的例子。效果圖如圖2:

圖2

代碼如下:

XAML <Window x:Class="Chapter_04.ControlBinding"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="ControlBinding" Height="300" Width="300"><StackPanel><TextBox x:Name="textBox1" Text="{Binding Path=Value,ElementName=slider1}"/><Slider x:Name="slider1" Maximum="100" Minimum="0" Margin="5"/></StackPanel> </Window>

下面講解主要代碼:

<TextBox x:Name="textBox1" Text="{Binding Path=Value,ElementName=slider1}"/>

  前面的文章XAML的語(yǔ)法記錄中已介紹過(guò)標(biāo)簽擴(kuò)展:特征是含有引號(hào)中{}而且開(kāi)始部分是其類(lèi)型。咋一看好像是Binding類(lèi)型的變量賦值給Text了,在這里可以把Binding看成一個(gè)函數(shù),整體的{}標(biāo)簽擴(kuò)展為一個(gè)函數(shù),返回值為Value。由于Binding帶一個(gè)路徑參數(shù)的構(gòu)造函數(shù),所以path=可以省略,寫(xiě)成這樣<TextBox x:Name="textBox1" Text="{Binding Value,ElementName=slider1}"/>,如果改成后臺(tái)代碼(C#)的話(huà)可以這么寫(xiě):

this.textBox1.SetBinding(TextBox.TextProperty, new Binding("Value") { ElementName="slider1"});

  我們前面說(shuō)過(guò),綁定是可以雙向的,這里如果先輸入值會(huì)不會(huì)讓slider1根據(jù)文本框中的值指到相應(yīng)的位置呢,答案是肯定的。那就去試試吧,試試的話(huà)好像沒(méi)有發(fā)現(xiàn)slider移動(dòng)啊?在這里還需要知道一點(diǎn),那就是Binding提供了數(shù)據(jù)流向的方向的屬性:Mode,它的類(lèi)型為BindingMode的枚舉類(lèi)型,可以取TwoWay、OneWay、OnTime、OneWayToSource、Default。在此肯定是默認(rèn)的了,Default是根據(jù)情況來(lái)確定的。其實(shí)在上面的例子中是雙向的,slider為什么不能移動(dòng)呢,是因?yàn)闆](méi)有textBox沒(méi)有失去焦點(diǎn),按一下Tab就可以看到效果了,每次想讓Slider移動(dòng)是不是必須要按一下Tab呢?肯定否定的,因?yàn)槲④泴?duì)應(yīng)Binding還提供了UpdateSourceTrigger屬性(描述綁定源更新的執(zhí)行時(shí)間),其值可以為PropertyChanged(當(dāng)綁定目標(biāo)屬性更改時(shí),立即更新綁定源,因?yàn)槭歉略?#xff0c;用于目標(biāo)對(duì)源的綁定,否則無(wú)效。多數(shù)依賴(lài)項(xiàng)屬性的默認(rèn)值為PropertyChanged,TextBox默認(rèn)值為L(zhǎng)ostFocus),Explicit(僅在調(diào)用 System.Windows.Data.BindingExpression.UpdateSource() 方法時(shí)更新綁定源),LostFocus。在這里,只需要在綁定里面加UpdateSourceTrigger=PropertyChanged就可以實(shí)現(xiàn)我們想要的結(jié)果了。除此之外Binding還有NotifyOnSourceUpdated和NotifyOnTargetUpdated屬性,設(shè)置為true的話(huà),當(dāng)源或目標(biāo)被更新后會(huì)激發(fā)相應(yīng)的SourceUpdated事件和TargetUpdated事件,實(shí)際工作中,我們還可以監(jiān)聽(tīng)兩個(gè)事件來(lái)找出有哪些數(shù)據(jù)更新了,或者是控件更新了。具體的用的時(shí)間在來(lái)細(xì)究,目前只記錄一下有這么一回事。

2.2 Binding的路徑(Path)

  Binding的源是一個(gè)對(duì)象,一個(gè)對(duì)象又會(huì)有多個(gè)屬性,通常我們要顯示的對(duì)象的某個(gè)屬性,就用Binding的路徑(Path)屬性來(lái)指定(有的時(shí)候也可以不指定Path),Path的實(shí)際類(lèi)型為PropertyPath。除此之外,有的對(duì)象的屬性也是對(duì)象、對(duì)象里面含有多個(gè)相同類(lèi)型的屬性取默認(rèn)值以及對(duì)象的索引,我們同樣可以指定它,下面通過(guò)例子來(lái)說(shuō)明,效果為圖3:

圖3

?

下面給出代碼:

XAML <Window x:Class="Chapter_04.Path"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="Path" Height="500" Width="805"><Grid Background="Gold"><Grid.RowDefinitions><RowDefinition Height="1*" /><RowDefinition Height="1*" /></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition/></Grid.ColumnDefinitions><!--源的屬性作Path--><Grid Background="Azure"><Grid.RowDefinitions><RowDefinition Height="1*" /><RowDefinition Height="1*" /><RowDefinition Height="1*" /><RowDefinition Height="1*" /></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition Width="1*"/><ColumnDefinition Width="2*"/></Grid.ColumnDefinitions><TextBlock Name="txtBlockPath1" Text="源的屬性作Path" VerticalAlignment="Bottom" HorizontalAlignment="Center" Grid.ColumnSpan="2" Grid.Row="0" /><TextBlock Name="txtBlock1" Text="計(jì)算文本框字符串的長(zhǎng)度" Height="25" VerticalAlignment="Bottom" HorizontalAlignment="Center" Grid.ColumnSpan="2" Grid.Row="1" /><TextBlock Name="textBlockString" Text="請(qǐng)輸入字符:" Height="25" Width="67" HorizontalAlignment="Right" Grid.Row="2" Grid.Column="0"/><TextBox Name="textBox" Width="240" Height="25" Grid.Column="2" Grid.Row="2" /><TextBlock Name="textBlockStringLong" Text="字符串長(zhǎng)度為:" HorizontalAlignment="Right" Height="23" Grid.Row="3" Grid.Column="0"/><TextBox Name="textBox1" Text="{Binding Path=Text.Length,ElementName=textBox,Mode=OneWay}" Width="240" Height="25" Grid.Row="3" Grid.Column="1" /></Grid><!--源的索引作Path--><Grid Background="Azure" Grid.Row="1" ><Grid.RowDefinitions><RowDefinition Height="1*" /><RowDefinition Height="1*" /><RowDefinition Height="1*" /><RowDefinition Height="1*" /></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition Width="1*"/><ColumnDefinition Width="2*"/></Grid.ColumnDefinitions><TextBlock Name="txtBlockPath2" Text="源的索引作Path" VerticalAlignment="Bottom" HorizontalAlignment="Center" Grid.ColumnSpan="2" Grid.Row="0" /><TextBlock Name="txtBlock2" Text="查看文本框字符串的第一個(gè)字符" Height="25" VerticalAlignment="Bottom" HorizontalAlignment="Center" Grid.ColumnSpan="2" Grid.Row="1" /><TextBlock Name="textBlockString1" Text="請(qǐng)輸入字符:" Height="25" Width="67" HorizontalAlignment="Right" Grid.Row="2" Grid.Column="0"/><TextBox Name="txtString1" Width="240" Height="25" Grid.Column="1" Grid.Row="2" /><TextBlock Name="textBlockStringLong1" Text="第一個(gè)字符為:" HorizontalAlignment="Right" Height="23" Grid.Row="3" Grid.Column="0"/><TextBox Name="txtFirstChar" Text="{Binding Path=Text.[0],ElementName=txtString1,Mode=OneWay}" Width="240" Height="25" Grid.Row="3" Grid.Column="1" /></Grid><!--默認(rèn)元素當(dāng)path--><Grid Background="Azure" Grid.Row="0" Grid.Column="1"><Grid.RowDefinitions><RowDefinition Height="1*" /><RowDefinition Height="1*" /><RowDefinition Height="1*" /><RowDefinition Height="1*" /></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition Width="1*"/><ColumnDefinition Width="2*"/></Grid.ColumnDefinitions><TextBlock Name="txtBlock3" Text="默認(rèn)元素當(dāng)path" Height="25" VerticalAlignment="Bottom" HorizontalAlignment="Center" Grid.ColumnSpan="2" Grid.Row="0" Grid.Column="1"/><TextBlock Name="textBlockString2" Text="名字:" Height="25" HorizontalAlignment="Right" Grid.Row="1" Grid.Column="0"/><TextBox Name="txtName" Width="240" Height="25" Grid.Column="1" Grid.Row="1" /><TextBlock Name="txtBlockSecondChar" Text="名字的第二個(gè)字符:" HorizontalAlignment="Right" Height="23" Grid.Row="2" Grid.Column="0"/><TextBox Name="txtSecondChar" Width="240" Height="25" Grid.Row="2" Grid.Column="1" /><TextBlock Name="textBlockStringLong3" Text="字符長(zhǎng)度為:" HorizontalAlignment="Right" Height="23" Grid.Row="3" Grid.Column="0"/><TextBox Name="txtLength" Width="240" Height="25" Grid.Row="3" Grid.Column="1" /></Grid><!--多級(jí)默認(rèn)元素當(dāng)path--><Grid Background="Azure" Grid.Row="1" Grid.Column="1"><Grid.RowDefinitions><RowDefinition Height="1*" /><RowDefinition Height="1*" /><RowDefinition Height="1*" /><RowDefinition Height="1*" /></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition Width="1*"/><ColumnDefinition Width="2*"/></Grid.ColumnDefinitions><TextBlock Name="txtBlock4" Text="多級(jí)默認(rèn)元素當(dāng)path" Height="25" VerticalAlignment="Bottom" HorizontalAlignment="Center" Grid.ColumnSpan="2" Grid.Row="0" Grid.Column="1"/><TextBlock Name="textBlockCountry" Text="國(guó)家:" Height="25" HorizontalAlignment="Right" Grid.Row="1" Grid.Column="0"/><TextBox Name="txtCountry" Width="240" Height="25" Grid.Column="1" Grid.Row="1" /><TextBlock Name="txtBlockProvince" Text="省份:" HorizontalAlignment="Right" Height="23" Grid.Row="2" Grid.Column="0"/><TextBox Name="txtProvince" Width="240" Height="25" Grid.Row="2" Grid.Column="1" /><TextBlock Name="textBlockCity" Text="城市:" HorizontalAlignment="Right" Height="23" Grid.Row="3" Grid.Column="0"/><TextBox Name="txtCity" Width="240" Height="25" Grid.Row="3" Grid.Column="1" /></Grid></Grid> </Window> CS 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.Shapes;namespace Chapter_04 {/// <summary>/// Path.xaml 的交互邏輯/// </summary>public partial class Path : Window{public Path(){InitializeComponent();//后臺(tái)代碼綁定路徑為屬性或者索引(索引也可以理解為特殊的屬性),當(dāng)綁定源本身就為string,int類(lèi)型數(shù)據(jù)時(shí)//XAML中可以省略路徑,后臺(tái)代碼中用"."代替,注意與下面“/”的區(qū)別//string str = "123";//this.txtName.SetBinding(TextBox.TextProperty, new Binding(".") { Source = str });//this.txtLength.SetBinding(TextBox.TextProperty, new Binding("Length") { Source = str, Mode = BindingMode.OneWay });//this.txtSecondChar.SetBinding(TextBox.TextProperty, new Binding("[1]") { Source = str, Mode = BindingMode.OneWay });//讓一個(gè)集合或者是DataView的第一個(gè)元素作為binding的路徑。如果路徑是集合的話(huà)可以繼續(xù)"/"下去===============================List<string> strList = new List<string>() { "Tim", "Tom", "Blog" };this.txtName.SetBinding(TextBox.TextProperty, new Binding("/") { Source = strList });this.txtLength.SetBinding(TextBox.TextProperty, new Binding("/Length") { Source = strList, Mode = BindingMode.OneWay });this.txtSecondChar.SetBinding(TextBox.TextProperty, new Binding("/[1]") { Source = strList, Mode = BindingMode.OneWay });//實(shí)現(xiàn)多級(jí)默認(rèn)集合作為binding的源=========================================================================================//定義一個(gè)國(guó)家列表List<Country> ListCountry = new List<Country>();//定義一個(gè)省份列表List<Province> ListProvince = new List<Province>();//定義一個(gè)城市列表List<City> ListCity1 = new List<City>();List<City> ListCity2 = new List<City>();//為城市列表中添加城市 ListCity1.Add(new City() { Name = "鄭州" });ListCity1.Add(new City() { Name = "許昌" });ListCity2.Add(new City() { Name = "福州" });ListCity2.Add(new City() { Name = "廈門(mén)" });//為省份列表添加省ListProvince.Add(new Province() { Name = "河南", CityList = ListCity1 });ListProvince.Add(new Province() { Name = "福建", CityList = ListCity2 });Country country = new Country() { Name = "中國(guó)", ProvinceList = ListProvince };ListCountry.Add(country);//當(dāng)默認(rèn)集合為對(duì)象的話(huà),注意指明其屬性,注意與上面的區(qū)分this.txtCountry.SetBinding(TextBox.TextProperty, new Binding("/Name") { Source = ListCountry });this.txtProvince.SetBinding(TextBox.TextProperty, new Binding("/ProvinceList/Name") { Source = ListCountry });this.txtCity.SetBinding(TextBox.TextProperty, new Binding("/ProvinceList/CityList/Name") { Source = ListCountry });}}#region 創(chuàng)建國(guó)家、省份、城市類(lèi)class City{public string Name { get; set; }}class Province{public string Name { get; set; }public List<City> CityList { get; set; }}class Country{public string Name { get; set; }public List<Province> ProvinceList { get; set; }}#endregion }

相對(duì)比較簡(jiǎn)單,代碼里面含有注釋,如有疑問(wèn)和不足的地方,歡迎留言。

2.3 為Binding指定源的方式

  Binding指定源的方式有多種,總的概括一句話(huà):只要一個(gè)對(duì)象包含數(shù)據(jù)并能通過(guò)屬性把數(shù)據(jù)暴露出來(lái),就能當(dāng)做Banding的源。下面列出常用的方法:

  • 把CLR類(lèi)型單個(gè)對(duì)象指定為Source,包括自帶的類(lèi)型對(duì)象和用戶(hù)自定義的對(duì)象,必要時(shí)使用INotifyPropertyChanged接口。可以通過(guò)在屬性的set語(yǔ)句里激發(fā)PropertyChanged事件來(lái)通知Binding數(shù)據(jù)已經(jīng)發(fā)生改變。
  • 把依賴(lài)對(duì)象指定為Source。一般情況依賴(lài)對(duì)象是用來(lái)作為Binding的目標(biāo)的,如果是作為源的話(huà),就形成了Binding鏈(源-目標(biāo)(源)-目標(biāo))。
  • 把DataContext指定為Source,由于每個(gè)WPF控件都含有DataContext屬性,DataContext常用于:如果不能確定Binding從哪里獲取數(shù)據(jù),只知道路徑Path的話(huà),他就會(huì)一直沿著控件樹(shù)往根的方向找下去,從而找到含有Path的元素的DataContext作為源。
  • 把普通CLR集合類(lèi)型對(duì)象指定為Source:包括數(shù)組、泛型等集合類(lèi)型。一般是把控件的ItemsSource屬性使用Binding關(guān)聯(lián)到一個(gè)集合對(duì)象上。
  • 把ADO.NET數(shù)據(jù)對(duì)象指定為Source:包括DataTable和DataView等對(duì)象。
  • XmlDataProvider把XML數(shù)據(jù)指定為source,經(jīng)常和TreeView和Menu結(jié)合著用(除了TreeView,還涉及到DataTemplate相關(guān)的內(nèi)容,如果不理解的話(huà),到“話(huà)模板“的時(shí)間在具體記錄)。
  • ObjectDataProvider對(duì)象指定為Source,當(dāng)數(shù)據(jù)源的屬性不是通過(guò)屬性而是通過(guò)方法來(lái)暴露的話(huà),就可以用ObjectDataProvider對(duì)象。
  • 通過(guò)Binding的RelativeSource屬性相對(duì)的指定Source,主要用于當(dāng)控件想關(guān)注自己或者自己容器的以及自己內(nèi)部元素的某個(gè)值就需要這個(gè)方法。

  由于前兩個(gè)已經(jīng)使用過(guò),下面就直接從第三個(gè)開(kāi)始逐個(gè)介紹。

2.4使用DataContext作為Binding的源

  先重點(diǎn)記錄一下DataContext,DataContext是每一個(gè)繼承FrameworkElement類(lèi)的控件都有的屬性,所以每一個(gè)UI控件都有此屬性(包括布局控件),Binding只知道Path不知道Source的話(huà)就會(huì)向UI樹(shù)的根部找過(guò),直到找到含有Path所指定的屬性的對(duì)象然后“借過(guò)來(lái)”用一下,如果最終沒(méi)有找到那么就不會(huì)得到數(shù)據(jù)。為了初步認(rèn)識(shí)一下DataContext,下面看一個(gè)例子:

<Window x:Class="Chapter_04.ContextSource"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="clr-namespace:Chapter_04"Title="ContextSource" Height="150" Width="219"><StackPanel Background="Beige"><StackPanel.DataContext><local:Student Id="2008101132" Age="24" Name="李占朋"/></StackPanel.DataContext><Grid><StackPanel><TextBox Text="{Binding Path=Id}" Margin="5" BorderBrush="Black"/><TextBox Text="{Binding Path=Name}" Margin="5" BorderBrush="Black"/><TextBox Text="{Binding Path=Age}" Margin="5" BorderBrush="Black"/></StackPanel></Grid></StackPanel> </Window>

后臺(tái)代碼為:

CS XAML 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.Shapes;namespace Chapter_04 {/// <summary>/// ContextSource.xaml 的交互邏輯/// </summary>public partial class ContextSource : Window{public ContextSource(){InitializeComponent();}}public class Student{public int Id { get; set; }public int Age { get; set; }public string Name { get; set; }} }

效果圖為圖4:

?

??????????????????????????????????? ????????????????????????????????????????????????????????????????????????????????

                    圖4                                           圖5

  在上面的例子中一個(gè)Student實(shí)例作為下面TextBox的綁定源。當(dāng)然{Binding Path=Age}部分可以把"Path="省略掉即{Binding Age}。突然發(fā)現(xiàn)DataContext指定源是沒(méi)有Source的Binding。是否能和沒(méi)有path(當(dāng)源為string或int類(lèi)型時(shí))的連用,如果可以,是怎么樣的效果呢?為了驗(yàn)證沒(méi)有找到Source只是不顯示數(shù)據(jù)但是不會(huì)報(bào)錯(cuò),我還用上面的部分代碼(圖5為效果圖):

<Window x:Class="Chapter_04.ContextSource"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:sys="clr-namespace:System;assembly=mscorlib"xmlns:local="clr-namespace:Chapter_04"Title="ContextSource" Height="150" Width="219"><StackPanel Background="Beige"><StackPanel.DataContext><!--<local:Student Id="2008101132" Age="24" Name="李占朋"/>--><sys:String>紅色部分為沒(méi)有Path的測(cè)試!</sys:String></StackPanel.DataContext><Grid><StackPanel><TextBlock Text="{Binding}" Background="Red"/><TextBox Text="{Binding Path=Id}" Margin="5" BorderBrush="Black"/><TextBox Text="{Binding Path=Name}" Margin="5" BorderBrush="Black"/><TextBox Text="{Binding Path=Age}" Margin="5" BorderBrush="Black"/></StackPanel></Grid></StackPanel> </Window>

嘿嘿,既沒(méi)有指定Source有沒(méi)有指定path的Binding出現(xiàn)了。下面看一下控件是怎么借用DataContext的。

主要的XAML代碼為

<Grid DataContext="借用測(cè)試"><Grid><Grid><Grid><Button x:Name="btn" Content="Ok" Click="btn_Click"/></Grid></Grid></Grid></Grid>

點(diǎn)擊按鈕事件代碼為:

private void btn_Click(object sender, RoutedEventArgs e){MessageBox.Show(btn.DataContext.ToString());}

?點(diǎn)擊按鈕效果圖為圖6:

圖6

  到這里應(yīng)該來(lái)說(shuō)基本上認(rèn)識(shí)了DataContext。而且從第一個(gè)例子中我們還可以看出:當(dāng)UI上多個(gè)控件使用Binding關(guān)注同一個(gè)對(duì)象,可以使用DataContext作為Binding的源。其實(shí)DataContext還是一個(gè)依賴(lài)屬性,我們可以使用Binding把他關(guān)聯(lián)到一個(gè)數(shù)據(jù)源上(先記著有這么一回事,在以后的記錄中會(huì)詳細(xì)分析)。

?2.5? 集合類(lèi)型對(duì)象指定列表控件的為ItemsSource

  前面的筆記中已經(jīng)記錄了ItemsControl控件,應(yīng)該有些熟悉了,它有個(gè)ItemsSource屬性,可以接受一個(gè)IEnumerable接口派生類(lèi)的實(shí)例作為自己的值。我們現(xiàn)在想辦法把指定的Path

顯示在ListBox中,先實(shí)現(xiàn)單個(gè)屬性的實(shí)現(xiàn),然后在實(shí)現(xiàn)多個(gè)屬性的顯示。單屬性顯示的代碼為:

XAML <Window x:Class="Chapter_04.ItemsSource"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="ItemsSource" Height="300" Width="300"><Grid Background="Beige"><TextBlock Text="所選學(xué)生的學(xué)號(hào):"></TextBlock><TextBox x:Name="textBoxid" Margin="0,1,93,234" HorizontalAlignment="Right" Width="82"></TextBox><ListBox x:Name="listview" Margin="0,89,62,0" Background="Azure"><!--<ListBox.ItemTemplate><DataTemplate><StackPanel Orientation="Horizontal"><TextBlock Text="{Binding Path=Id}" Width="30"/><TextBlock Text="{Binding Path=Name}" Width="30"/><TextBlock Text="{Binding Path=Age}" Width="30"/></StackPanel></DataTemplate></ListBox.ItemTemplate>--></ListBox><Button Content="添加學(xué)生" Height="23" HorizontalAlignment="Left" Margin="191,0,0,0" VerticalAlignment="Top" Width="75" Click="button1_Click" /></Grid> </Window> CS 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.Shapes; using System.Collections.ObjectModel;namespace Chapter_04 {/// <summary>/// ItemsSource.xaml 的交互邏輯/// </summary>public partial class ItemsSource : Window{//注意ObservableCollection與List的區(qū)別List<Student> stuList = new List<Student>() { new Student(){Id=0,Name="Tim",Age=19},new Student(){Id=1,Name="Tom",Age=29},new Student(){Id=2,Name="jim",Age=39},};public ItemsSource(){InitializeComponent();listview.ItemsSource = stuList;this.listview.DisplayMemberPath = "Name";Binding binding = new Binding("SelectedItem.Id") { Source = this.listview };this.textBoxid.SetBinding(TextBox.TextProperty, binding);}private void button1_Click(object sender, RoutedEventArgs e){this.stuList.Add(new Student() { Id = 2, Name = "jim", Age = 39 }); }} }

  在CS代碼中,我們看到了一句this.listview.DisplayMemberPath = "Name"中有一個(gè)DisplayMemberPath,這個(gè)就是指定綁定源的屬性。如果想顯示多個(gè)屬性,應(yīng)該怎么做呢?答案是使用DataTemplate,因?yàn)樵谝院蟮墓P記中還會(huì)記錄到DataTemplate,在此提出來(lái)知道有這么一回事就好了,接觸過(guò)webFrom的人或許會(huì)理解的更快點(diǎn)。具體的做法是把上面的XAML代碼中的注釋部分去掉,后臺(tái)代碼的this.listview.DisplayMemberPath = "Name";去掉就可以實(shí)現(xiàn)顯示多個(gè)屬性。除此之外我在UI上還放了一個(gè)Button,主要用來(lái)區(qū)別ObservableCollection<T>與List<T>,因?yàn)镺bservableCollection<T>實(shí)現(xiàn)了INotifyColletionChanged和INotifyProperty接口,能把集合的變化立即顯示給控件。可以把后臺(tái)代碼的List用ObservableCollection替代,點(diǎn)擊按鈕查看兩者的區(qū)別(添加的條目會(huì)理解顯示出來(lái),用list卻沒(méi)有這個(gè)效果)。

2.6?把ADO.NET數(shù)據(jù)對(duì)象指定為Source

  基本上和上面的用法相同,但是注意格式,特別是GridView的用法.

View Code <Window x:Class="Chapter_04.Ado"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="Ado" Height="300" Width="400"><StackPanel><ListView x:Name="listView1"><ListView.View><GridView><GridViewColumn Header="學(xué)號(hào)" Width="60" DisplayMemberBinding="{Binding UserNo}"/><GridViewColumn Header="昵稱(chēng)" Width="60" DisplayMemberBinding="{Binding UserName}"/><GridViewColumn Header="姓名" Width="60" DisplayMemberBinding="{Binding UserRealName}"/><GridViewColumn Header="郵箱" Width="120" DisplayMemberBinding="{Binding UserEmail}"/></GridView></ListView.View></ListView></StackPanel> </Window> CS View Code 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.Shapes; using System.Data;namespace Chapter_04 {/// <summary>/// Ado.xaml 的交互邏輯/// </summary>public partial class Ado : Window{public DataTable dt = null;public Ado(){IntiData();InitializeComponent();//this.listView1.ItemsSource = dt.DefaultView;this.listView1.DataContext = dt;this.listView1.SetBinding(ListView.ItemsSourceProperty,new Binding());}private void IntiData(){dt = new DataTable("T_User");dt.Columns.Add("UserNo", typeof(string));dt.Columns.Add("UserName", typeof(string));dt.Columns.Add("UserRealName", typeof(string));dt.Columns.Add("UserEmail", typeof(string));dt.Columns.Add("UserAddress", typeof(string));for (int i = 0; i < 10; i++){DataRow dr = dt.NewRow();dr["UserNo"] = "10000" + i.ToString();dr["UserName"] = "haiziguo";dr["UserRealName"] = "李占朋";dr["UserEmail"] = "lizhpeng@126.com";dt.Rows.Add(dr);}}} }

?

顯示結(jié)果如圖7:

?

圖7

  通過(guò)上面的一個(gè)演示,我們應(yīng)該知道ListView和GridView不是同一級(jí)別的控件,GridView是作為L(zhǎng)istView的View屬性的值,其中View和GridView都是屬于ViewBase類(lèi)型對(duì)象。如果不是很理解的話(huà),在模板筆記里面還會(huì)具體的記錄。還有個(gè)地方是"this.listView1.ItemsSource = dt.DefaultView;“DataTable是不能直接賦值給ItemsSource的,如果賦值可以用DefaultView屬性。把這一句取消注釋,然后注釋掉下面的兩行,可以看到相同的結(jié)果。

2.7 XmlDataProvider把XML數(shù)據(jù)指定為source

  XML是什么以及xml的用途,在此不作為重點(diǎn),本文重點(diǎn)介紹怎么把XML綁定到UI控件中。?XmlDataProvider就是把XML數(shù)據(jù)作為數(shù)據(jù)源提供給Binding。下面實(shí)現(xiàn)一個(gè)需求,就是把XML的數(shù)據(jù)顯示在TreeViewItem里面。先給出XML文件,然后分別給出XAML和CS代碼:

XML <?xml version="1.0" encoding="utf-8" ?> <Department Name="公司部門(mén)"><Department Name="軟件組"><Department Name="Tom"/><Department Name="Tom1"/></Department><Department Name="客服組"><Department Name="Tim"/><Department Name="Tim1"/></Department> </Department> XAML <Window x:Class="Chapter_04.Source"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="Source" Height="312" Width="1090"><StackPanel Orientation="Horizontal"><Grid Width="150"><TreeViewItem><TreeViewItem.Header>各個(gè)部門(mén)以及其成員</TreeViewItem.Header><TreeView x:Name="treeViewDepartment"><TreeView.ItemTemplate><HierarchicalDataTemplate ItemsSource="{Binding XPath=Department}"><TextBlock Text="{Binding XPath=@Name}"/></HierarchicalDataTemplate></TreeView.ItemTemplate></TreeView></TreeViewItem></Grid></StackPanel> </Window> CS 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.Shapes;namespace Chapter_04 {/// <summary>/// Source.xaml 的交互邏輯/// </summary>public partial class Source : Window{public Source(){InitializeComponent();XmlDataProvider xdp = new XmlDataProvider();xdp.Source = new Uri(@"E:\WPFCode\Chapter_04\Chapter_04\Department.xml");xdp.XPath = @"/Department";treeViewDepartment.DataContext = xdp;treeViewDepartment.SetBinding(TreeView.ItemsSourceProperty, new Binding());}} }

另外一種寫(xiě)法思路是把XML文件當(dāng)做資源,然后在前臺(tái)綁定:

View Code <Window x:Class="Chapter_04.Source"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="Source" Height="312" Width="1090"><StackPanel Orientation="Horizontal"><Grid Width="150"><TreeViewItem><TreeViewItem.Header>各個(gè)部門(mén)以及其成員</TreeViewItem.Header><TreeView x:Name="treeViewDepartment" ItemsSource="{Binding Source={StaticResource ResourceKey=xmlDepartment}}"><TreeView.ItemTemplate><HierarchicalDataTemplate ItemsSource="{Binding XPath=Department}"><TextBlock Text="{Binding XPath=@Name}"/></HierarchicalDataTemplate></TreeView.ItemTemplate></TreeView></TreeViewItem></Grid></StackPanel> </Window> CS 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.Shapes;namespace Chapter_04 {/// <summary>/// Source.xaml 的交互邏輯/// </summary>public partial class Source : Window{public Source(){InitTreeView();InitializeComponent();}protected void InitTreeView(){XmlDataProvider xdp = new XmlDataProvider();xdp.Source = new Uri(@"E:\WPFCode\Chapter_04\Chapter_04\Department.xml");xdp.XPath = @"/Department";this.Resources.Add("xmlDepartment",xdp);}}}

效果圖為圖8:

?圖8

?  簡(jiǎn)單的實(shí)現(xiàn)了讓XML的文件顯示到了TreeViewItem,但是美中不足的是這里用到了HierarchicalDataTemplate模板,不過(guò)作為一個(gè)參考吧,或者等到介紹完Template再回來(lái)看看也不錯(cuò)。最后要注意的是:關(guān)于綁定的時(shí)間<TextBlock Text="{Binding XPath=@Name}"/>?里面加@表示Attribute,不加@的話(huà)表示子集元素。

?2.8 ObjectDataProvider對(duì)象指定為Source

  Binding的源不僅可以是通過(guò)XmlDataProvider提供的XML數(shù)據(jù),還可以是ObjectDataProvider類(lèi)提供的類(lèi)的實(shí)例。XmlDataProvider與ObjectDataProvider都是繼承于抽象類(lèi)DataSourceProvider。下面用個(gè)圖來(lái)解釋一下ObjectDataProvider對(duì)象,如圖9:

圖9

?  其中ObjectDataProvider對(duì)象的ObjectInstance屬性是類(lèi)的實(shí)例化對(duì)象(Obj),MethodParamers屬性為Obj的方法,其中方法中還可以含有參數(shù)。最后返回結(jié)果為ObjectDataProvider對(duì)象的Data屬性。?這樣做的結(jié)果是更方便了程序員的分工,很簡(jiǎn)單的就綁定了一個(gè)返回值。?下面實(shí)現(xiàn)一個(gè)加法的運(yùn)算:

Calculator.cs using System; using System.Collections.Generic; using System.Linq; using System.Text;namespace Chapter_04 {public class Calculator{public string Add(string arg1, string arg2){double x = 0; double y = 0; double z = 0;if (double.TryParse(arg1, out x) && double.TryParse(arg2, out y)){z = x + y;return z.ToString();}return "input Error";}} } XAML <Window x:Class="Chapter_04.ObjectDataProviderTest"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="ObjectDataProviderTest" Height="300" Width="300"><StackPanel Background="LightBlue"><TextBox Name="FristParam" Margin="5" ></TextBox><TextBox Name="SecondParam" Margin="5" ></TextBox><TextBox Name="Result" Margin="5"></TextBox></StackPanel> </Window> CS 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.Shapes;namespace Chapter_04 {/// <summary>/// ObjectDataProviderTest.xaml 的交互邏輯/// </summary>public partial class ObjectDataProviderTest : Window{public ObjectDataProviderTest(){InitializeComponent();SetBinding();}private void SetBinding(){ObjectDataProvider odp = new ObjectDataProvider();odp.ObjectInstance = new Calculator();odp.MethodName = "Add";odp.MethodParameters.Add("0");odp.MethodParameters.Add("0");//MessageBox.Show(odp.Data.ToString());Binding bindArg1 = new Binding("MethodParameters[0]"){Source = odp,//把UI元素收集到的元素直接賦給sourceBindsDirectlyToSource = true,//當(dāng)目標(biāo)更改時(shí),立即設(shè)置新的源UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged};Binding bindArg2 = new Binding("MethodParameters[1]"){Source = odp,BindsDirectlyToSource = true,UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged};Binding bindingToResult = new Binding(".") { Source = odp };this.FristParam.SetBinding(TextBox.TextProperty, bindArg1);this.SecondParam.SetBinding(TextBox.TextProperty, bindArg2);this.Result.SetBinding(TextBox.TextProperty, bindingToResult);}} }

運(yùn)行,如果在前兩個(gè)文本框里面填上數(shù)字,結(jié)果就會(huì)出現(xiàn)了;如圖10

圖10

  ObjectDataProvider對(duì)象作為綁定源還是很遵守“使用數(shù)據(jù)對(duì)象作為源,UI控件作為綁定對(duì)象”的原則,但是關(guān)于this.Result.SetBinding(TextBox.TextProperty,new Binding(".") { Source=odp});用“.”而不用“Data”來(lái)表示路徑,我不是很理解,如果有大牛知道的話(huà),歡迎留言。?

?2.9 通過(guò)Binding的RelativeSource屬性相對(duì)的指定Source

  綁定的源不僅用"絕對(duì)"的對(duì)象,還可以用“相對(duì)”的作為源。例如有的時(shí)間我們需要顯示出上級(jí)的控件的寬度。需求是:將上級(jí)的第一個(gè)(從自身向上數(shù)起第一個(gè))Grid的寬度顯示在TextBox里面,由于比較簡(jiǎn)單,現(xiàn)在直接貼出代碼。  

XAML <Window x:Class="RelativeSounceOfBinding.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="MainWindow" Height="350" Width="525"><Grid x:Name="g1" Background="Red" Margin="10"><DockPanel x:Name="d1" Background="Orange" Margin="10"><Grid x:Name="g2" Background="Yellow" Margin="10" Width="300"><DockPanel x:Name="d2" Background="LawnGreen" Margin="10"><TextBox Name="textBox1" FontSize="24" Margin="10" Background="AliceBlue" /></DockPanel></Grid></DockPanel></Grid> </Window> CS 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;namespace RelativeSounceOfBinding {/// <summary>/// MainWindow.xaml 的交互邏輯/// </summary>public partial class MainWindow : Window{public MainWindow(){InitializeComponent();RelativeSource rs = new RelativeSource();rs.AncestorLevel = 1;rs.AncestorType = typeof(Grid);Binding bind=new Binding("Width"){RelativeSource=rs};this.textBox1.SetBinding(TextBox.TextProperty, bind);}} }

效果圖如圖11:

圖11

RelativeSource rs = new RelativeSource();rs.AncestorLevel = 1;rs.AncestorType = typeof(Grid);

此處的源是RelativeSource類(lèi)型的實(shí)例。AncestorLevel是指定向上查第幾個(gè)類(lèi)型為AncestorType的控件。順便附上XAML實(shí)現(xiàn)的方法:

<TextBox Name="textBox1" FontSize="24" Margin="10" Background="AliceBlue" Text="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Grid},AncestorLevel=1},Path=Width}" />

三、總結(jié)

  由于綁定與模板聯(lián)系比較緊密,所以有的地方會(huì)用到模板,難免會(huì)有似懂非懂的感覺(jué),不過(guò)等做完模板的筆記的話(huà),再回來(lái)看,應(yīng)該會(huì)慢慢的消化的。綁定在WPF中是比較重要的一章,在本文中僅僅是幾個(gè)記錄。鑒于文章寫(xiě)的太長(zhǎng)自己堅(jiān)持不住寫(xiě),另一方面到時(shí)間復(fù)習(xí)的話(huà)也沒(méi)有耐心看,所以就把綁定分為兩篇去記錄,下一篇《深入淺出WPF》筆記——綁定篇(二)會(huì)記錄Binding對(duì)數(shù)據(jù)的轉(zhuǎn)化和校驗(yàn)以及多路綁定。

轉(zhuǎn)載于:https://www.cnblogs.com/lzhp/archive/2012/09/11/2673810.html

總結(jié)

以上是生活随笔為你收集整理的《深入浅出WPF》笔记——绑定篇(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。