欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
《深入淺出WPF》學(xué)習筆記之深入淺出話(huà)Binding

第6章 深入淺出話(huà)Binding

6.2 Binding基礎

  如果把Binding比作數據的橋梁,那么它的兩端分別是Binding的(Source)和目標(Target)。一般源是邏輯層對象,目標是UI層控件對象.

  我們可以控制源與目標是雙向通行還是單向,還可以控制對數據放行的時(shí)機,還可以設置“關(guān)卡”轉換數據類(lèi)型或校驗數據的正確性。

class Student{ public string Name {get;set;} public string Age {get;set;}}

  Path:如上所示,一個(gè)對象有多個(gè)屬性,UI上關(guān)心哪個(gè)屬性值的變化呢?這個(gè)屬性就稱(chēng)為Binding的路徑(Path)

  PropertyChanged:讓屬性具備通知Binding值已變化的能力。作為數據源的類(lèi)實(shí)現INotifyPropertyChanged接口。

using System.ComponentModel; class Student : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private string name; public string Name { get { return name; } set { name = value; //激發(fā)事件 if (this.PropertyChanged != null) { this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Name")); } } } }

  Binding的過(guò)程:

Student stu = new Student();Binding binding = new Binding();binding.Source = stu;binding.Path = new PropertyPath("Name");
BindingOperations.SetBinding(this.textBoxName,TextBox.TextProperty,binding);

  主要是 源、路徑、設置綁定

  

  實(shí)際工作中,實(shí)施Binding的代碼可能與上面不太一樣,因為T(mén)extBox這類(lèi)UI元素的基類(lèi)FramewordElement對BindingOperation.SetBinding(...)方法進(jìn)行了封裝,封裝的結果也叫SetBinding,只是參數列表發(fā)送了變化  

public BindingExpressionBase SetBinding(DependencyProperty dp, BindingBase binding) { return BindingOperations.SetBinding(this, dp, binding); }

  借助Binding類(lèi)的構造器及C#3.0的對象初始化器語(yǔ)法簡(jiǎn)化上述代碼

this.textBoxName.SetBinding(TextBox.TextProperty, new Binding("Name") { Source = stu = new Student() });

6.3 Binding的源與路徑

  源:只要是一個(gè)對象,并行通過(guò)屬性(Property)公開(kāi)自己的數據,它就能作為Binding的源

     如果想讓作為Binding源的對象具有自動(dòng)通知Binding屬性已改變的能力,就需要讓類(lèi)實(shí)現InotifyPropertyChanged接口并在熟悉的set語(yǔ)句中激發(fā)PropertyChanged事件。

       除了對象作為數據源外,還可以有很多選擇,控件自己或自己的容器或子集元素、集合作為ItemsControl的數據源、XML作為T(mén)reeView或Menu的數據源、把多個(gè)控件關(guān)聯(lián)到一個(gè)“數據制高點(diǎn)”上、甚至干脆不給Binding指定數據源,讓它自己去找

6.3.1 把控件作為Binding源與Binding標記拓展

  大多數情況下Binding的源是邏輯層對象,但有時(shí)候為了讓UI元素產(chǎn)生聯(lián)動(dòng)效果也會(huì )使用Binding在控件間建立關(guān)聯(lián)。

  如把TextBox的Text屬性關(guān)聯(lián)在Slider的Value屬性上

<StackPanel> <TextBox x:Name="textBox1" Text="{Binding Path=Value,ElementName=slider1}" BorderBrush="Black" Margin="5"/> <Slider x:Name="slider1" Maximum="100" Minimum="0" Margin="5"/> </StackPanel>

  

  

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

  與下面C#代碼等價(jià),且上面Path=可以省略

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

  

  wpf數據綁定SourceElementName的區別

  • Source 用于指定數據源為后臺數據對象、集合

  • ElementName 用于指定“數據源”為界面上某個(gè)控件的某個(gè)屬性

  注意:

  在C#代碼中可以訪(fǎng)問(wèn)XAML代碼中聲明的變量,但XAML代碼中無(wú)法訪(fǎng)問(wèn)C#代碼中聲明的變量。

  因此,要想在XAML中建立UI元素與邏輯層對象的Binding還要頗費些周折,把邏輯層對象聲明為XAML代碼中的資源(Resource),見(jiàn)資源一章。

6.3.2 控制Bangding的方向及數據更新

  有時(shí)候數據只需要展示給用戶(hù)、不允許用戶(hù)修改,這時(shí)候可以把Binding模式更改為從源向目標的單向溝通 (源→目標:OneWay

  Mode:屬性Mode控制綁定方向。BindingMode類(lèi)型的枚舉值:TwoWay、OneWay、OnTime、OneWayToSource和Default?!?  

  • TwoWay  源?目標  無(wú)論是目標屬性還是源屬性,只要發(fā)生了更改,TwoWay 就會(huì )更新目標屬性或源屬性。

  • OneWay  源→目標  僅當源屬性發(fā)生更改時(shí)更新目標屬性。

  • OneTime 僅當應用程序啟動(dòng)時(shí)或 DataContext 進(jìn)行更改時(shí)更新目標屬性。

  • OneWayToSource  目標→源  在目標屬性更改時(shí)更新源屬性。

  • Default 使用目標屬性的默認 Mode 值。(這里的Default指的是Binding的模式會(huì )根據目標是實(shí)際情況來(lái)確定,如果是可以編輯的(TextBox的Text屬性),Default就采用雙向模式。如果是TextBlock,不可編輯,就使用單向模式。

  上述Slider示例中,在TextBox輸入一個(gè)值,然后按Tab鍵(TextBox丟失焦點(diǎn)),Slider的手柄會(huì )自動(dòng)跳到相應的位置。

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

  為什么一定要丟失焦點(diǎn)后Slider的值才變呢?

  UpdateSourceTrigger:屬性控制值改變時(shí)機。枚舉值PropertyChanged、LostFocus、Explicit和Default

 

Explicit,源不會(huì )更新除非你手動(dòng)來(lái)操作
LostFocus,一旦目標控件失去焦點(diǎn),源就會(huì )被更新。
PropertyChanged,一旦綁定的屬性值改變,源會(huì )立即更新。

View Code

6.3.3 Binding的路徑(Path)

  即綁定到底需要關(guān)注哪個(gè)屬性的值。前面例子是把Slider控件當做源,它的Value作為路徑

  Path屬性對應c#的實(shí)際類(lèi)型是PropertyPath

Binding binding = new Binding(){Path=new PropertyPath("Value"),Source=this.slidr1};

  Path支持多級路徑(即一路“點(diǎn)”下去)

       如 {Binding Path=Text.Length} 

  如果集合作為源,想把集合中的元素當做Path可以使用多級斜杠的方式

  如 new Binding("/Name")   new Binding("/ProvinceList.Name") 

6.3.4 沒(méi)有Path的Binding

  有點(diǎn)時(shí)候Path是一個(gè). 或者干脆沒(méi)有Path

  這是一種特殊的情況——Binding源本身就是數據且不需要Path來(lái)指明

  如string、int等基本類(lèi)型,可以將Path設置為".",XAML中.可以省略,C#代碼中不可以省

6.3.5 為Binding指定源(Source)的幾種方式

   Binding的源是數據的來(lái)源,只要一個(gè)對象包含數據并能通過(guò)屬性獲取到,它就能當作Binding的源

  *普通CLR類(lèi)型對象,只要改對象實(shí)現了INotifyPropertyChanged接口即可當作源

  *普通CLR集合類(lèi)型對象:數組、List<T>、ObservableCollection<T>

    經(jīng)常把集合作為ItemsControl派生類(lèi)的數據源

  *ADO.NET數據對象:DataTable和DataView等

  *XML,使用XmlDataProvider

  *依賴(lài)對象(Dependency Object)

  *容器的DataContext (WPF默認使用的源)

  *ElementName指定源:在C#代碼中把對象的Name作為源賦給Binding

  *RelativeSource指定源:當控件需要關(guān)注自己的、自己容器的或者自己內部元素的某個(gè)值時(shí)

  *ObjectDataProvider:當數據源的數據不是通過(guò)屬性而是通過(guò)方法暴露給外界時(shí)

  *LINQ檢索得到的數據對象

下面通過(guò)實(shí)例分述每種情況

6.3.6 沒(méi)有Source的Binding——使用DataContext作為Binding的源

   所有WPF控件(包括容器控件)都具備DataContext屬性

   在UI元素樹(shù)的每個(gè)節點(diǎn)都有DataContext

public class Student { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } } <StackPanel Background="LightBlue" > <StackPanel.DataContext> <local:Student Id="6" Age="29" Name="tim"/> </StackPanel.DataContext> <Grid > <StackPanel> <TextBox Text="{Binding Path=Id}" Margin="5"/> <TextBox Text="{Binding Path=Name}" Margin="5" /> <TextBox Text="{Binding Path=Age}" Margin="5"/> </StackPanel> </Grid> </StackPanel>

UI布局如下

  

  在XAML中為外層StackPanel的DataContext賦了值,內層TextBox的Binding只指定了Path,沒(méi)有指定Source,這時(shí)TextBox的Binding會(huì )自動(dòng)向UI元素樹(shù)的上層尋找可用的DataContext對象

  如果Source本身就是數據,Binding的Path可以設置為"."或不寫(xiě)

  

xmlns:sys="clr-namespace:System;assembly=mscorlib"
<StackPanel Background="LightBlue" > <StackPanel.DataContext> <sys:String >Hello DataContext!</sys:String> </StackPanel.DataContext> <Grid > <StackPanel> <TextBlock Text="{Binding}" Margin=" 5"/> <TextBlock Text="{Binding .}" Margin=" 5"/> </StackPanel> </Grid></StackPanel>

   此處使用TextBlock,如果使用TextBox提示 雙向綁定需要Path或Xpath 

  

  其實(shí),“Binding沿著(zhù)UI元素樹(shù)網(wǎng)上找”只是WPF給我們的一個(gè)錯覺(jué),實(shí)際是因為DataContext是一個(gè)“依賴(lài)屬性”,當控件的依賴(lài)屬性沒(méi)有顯式賦值時(shí),依賴(lài)屬性值會(huì )沿UI元素樹(shù)向下傳遞。

  DataContext的用法:

  *當UI上多個(gè)控件Binding同一個(gè)對象時(shí)

  *當Source對象不能被直接訪(fǎng)問(wèn)時(shí)——比如B窗體內的控件想把A窗體內的控件當做Binding源,但A窗體內的控件是private訪(fǎng)問(wèn)級別,這時(shí)可以把該控件作為窗體A的DataContext

6.3.7 使用集合作為列表控件的ItemsSource

  WPF中的列表控件派生自ItemsControl類(lèi),自然繼承了ItemsSource屬性。ItemsSource屬性可以接收IEnumerable接口派生類(lèi)的實(shí)例作為自己的值。

  每個(gè)ItemsControl的派生類(lèi)都有自己對應的條目容器(Item Container)。例如 ListBox -> ListBoxItem   ComboBox -> ComboBoxItem 

 
 <StackPanel x:Name="stackPanel" Background="LightBlue" >    <TextBlock Text="Student ID:" FontWeight="Bold" Margin="5" />    <TextBox x:Name="textBoxId" Margin="5"/>    <TextBlock Text="Student List:" FontWeight="Bold" Margin="5"/>    <ListBox x:Name="listBoxStudents" Height=" 110" Margin=" 5" />  </StackPanel>

 
 List<Student> stuList = new List<Student>()  {    new Student() { Id=0,Name="Tim",Age=29},    new Student() { Id=1,Name="Tom",Age=28},  }; //為L(cháng)istBox設置Binding  this.listBoxStudents.ItemsSource = stuList;  this.listBoxStudents.DisplayMemberPath = "Name";
//為T(mén)extBox設置Binding  Binding binding = new Binding("SelectedItem.Id") { Source = this.listBoxStudents };  this.textBoxId.SetBinding(TextBox.TextProperty, binding);

  注意:DisplayMemberPath屬性賦值后,ListBox就以ItemsSource源下ListBoxItem變量的Path為Binding

   

<StackPanel x:Name="stackPanel" Background="LightBlue" >  <TextBlock Text="Student ID:" FontWeight="Bold" Margin="5" />  <TextBox x:Name="textBoxId" Margin="5"/>  <TextBlock Text="Student List:" FontWeight="Bold" Margin="5"/>  <ListBox x:Name="listBoxStudents" Height=" 110" Margin=" 5" >    <ListBox.ItemTemplate >      <DataTemplate >        <StackPanel Orientation="Horizontal">          <TextBlock Text="{Binding Path=Id}" Width="30" />          <TextBlock Text="{Binding Path=Name}" Width="60" />          <TextBlock Text="{Binding Path=Age}" Width="30" />        </StackPanel>      </DataTemplate>    </ListBox.ItemTemplate>  </ListBox></StackPanel>

List<Student> stuList = new List<Student>(){ new Student() { Id=0, Name="Tim", Age=29 }, new Student() { Id=1, Name="Tom", Age=28 },};this.listBoxStudents.ItemsSource = stuList;//this.listBoxStudents.DisplayMemberPath = "Name"; this.textBoxId.SetBinding(TextBox.TextProperty, new Binding("SelectedItem.Id"){Source = this.listBoxStudents});

  去掉DisplayMemberPath賦值,顯示的為數據設置DataTemplate后,結果如上右圖所示

6.3.8 使用ADO.NET對象作為Binding的源

  盡管流行的架構中先通過(guò)Linq等手段把DataTable里的數據轉換成用戶(hù)自定義類(lèi)型集合,但WPF也可以讓列表控件和DataTable直接建立Binding

<StackPanel x:Name="stackPanel" Background="LightBlue" > <ListBox x:Name="listBoxStudents" Height=" 110" Margin=" 5" /></StackPanel>DataTable dt = new DataTable();dt.Columns.Add("Id", Type.GetType("System.String"));dt.Columns.Add("Name", Type.GetType("System.String"));dt.Columns.Add("Age", Type.GetType("System.String"));
dt.Rows.Add(new object[] { "1", "Tim", "29" });dt.Rows.Add(new object[] { "2", "Tom", "28" });dt.Rows.Add(new object[] { "3", "Tony", "27" });dt.Rows.Add(new object[] { "4", "Kyle", "26" });
this.listBoxStudents.ItemsSource = dt.DefaultView;this.listBoxStudents.DisplayMemberPath = "Name";

  

  上面采用DefaultView,多數情況下,我們會(huì )選擇ListView控件來(lái)顯示DataTable,結果如上圖右

<StackPanel x:Name="stackPanel" Background="LightBlue" > <ListView x:Name="listViewStudents" Height=" 110" Margin="5" > <ListView.View> <GridView> <GridViewColumn Header="ID" Width="60" DisplayMemberBinding="{Binding Id}" /> <GridViewColumn Header="Name" Width="80" DisplayMemberBinding="{Binding Name}" /> <GridViewColumn Header="Age" Width="60" DisplayMemberBinding="{Binding Age}" /> </GridView> </ListView.View> </ListView></StackPanel>

   注意:ListView和GridView看著(zhù)像同一級別的控件,實(shí)際并非如此。ListView是一個(gè)控件,GridView是ListView的View(目前ListView只有此唯一的一個(gè)View  2010年)

  GridViewColumn 屬于 <GridView.Columns> 節點(diǎn)下,此處可以省略此節點(diǎn)

  我們把DataTable.DefaultView作為ItemsSource,如果直接用DataTable作為源會(huì )報錯,但可以把DataTable對象賦給DataContext,然后設置一個(gè)無(wú)源無(wú)路徑的綁定

this.listViewStudents.DataContext = dt;this.listViewStudents.SetBinding(ListView.ItemsSourceProperty, new Binding());

6.3.9 使用XML數據作為Binding的源

  XML文本是樹(shù)形結構,可以方便表示線(xiàn)性集合(Array、List等)和樹(shù)形結構數據

  當使用XML作為源時(shí),路徑使用XPath而不是Path

<?xml version="1.0" encoding="utf-8" ?> //RawData.xml<StudentList> <Student Id="1"> <Name>Tim</Name> </Student> <Student Id="2"> <Name>Tom</Name> </Student> <Student Id="3"> <Name>Vina</Name> </Student> <Student Id="4"> <Name>Emily</Name> </Student></StudentList><StackPanel x:Name="stackPanel" Background="LightBlue" > <ListView x:Name="listViewStudents" Height=" 110" Margin=" 5" > <ListView.View> <GridView >                 //加@表示屬性,不加@表示子級元素 <GridViewColumn Header="ID" Width="60" DisplayMemberBinding="{Binding XPath=@Id}" /> <GridViewColumn Header="Name" Width="80" DisplayMemberBinding="{Binding XPath=Name}" /> </GridView> </ListView.View> </ListView></StackPanel>

//方法1 //XmlDocument doc = new XmlDocument();//doc.Load(@"D:\RawData.xml");//XmlDataProvider xdp = new XmlDataProvider();//xdp.Document = doc;//xdp.XPath = @"/StudentList/Student"; //使用Xpath選擇需要暴露的數據
//方法2XmlDataProvider xdp = new XmlDataProvider();xdp.Source = new Uri(@"D:\RawData.xml");xdp.XPath = @"/StudentList/Student";
this.listViewStudents.DataContext = xdp;this.listViewStudents.SetBinding(ListView.ItemsSourceProperty, new Binding());


6.3.10 使用Linq檢索結果作為Binding的源

  使用Linq我們可以方便地操作集合、DataTable和XML對象而不必動(dòng)輒好幾層foreach循環(huán)嵌套只是為了完成一個(gè)簡(jiǎn)單的任務(wù)

  Linq查詢(xún)的結果是IEnumerable<T>類(lèi)型對象,它派生自IEnumerable,所以它可以作為列表控件的ItemsSource來(lái)使用

List<Student> stuList = new List<Student>(){ new Student() { Id=0, Name="Tim", Age=29 }, new Student() { Id=1, Name="Tom", Age=28 }, new Student() { Id=2, Name="Kyle", Age=27 }, new Student() { Id=3, Name="Tony", Age=26 }, new Student() { Id=4, Name="Vina", Age=25 }, new Student() { Id=5, Name="Mike", Age=24 },};
this.listViewStudents.ItemsSource = from stu in stuList where stu.Name.StartsWith("T") select stu;//數據在XMLthis.listViewStudents.ItemsSource = from element in xdoc.Descendants("Student") where element.Attribute("Name").Value.StartsWith("T") select new Student() { Id = int.Parse(element.Attribute("Id").Value), Name = element.Attribute("Name").Value, Age = int.Parse(element.Attribute("Age").Value) };

6.3.11 使用ObjectDataProvider對象作為Binding的Source

  ObjectDataProvider顧名思義就是把對象作為數據源提供給Binding

<StackPanel Background="LightBlue" > <TextBox x:Name="textBoxArg1" Margin="5"></TextBox> <TextBox x:Name="textBoxArg2" Margin="5"></TextBox> <TextBox x:Name="textBoxResult" Margin="5"></TextBox></StackPanel>

//創(chuàng )建并配置ObjectDataProvider對象ObjectDataProvider odp = new ObjectDataProvider(); odp.ObjectInstance = new Calculator();odp.MethodName = "Add";odp.MethodParameters.Add("0");odp.MethodParameters.Add("0");
//以ObjectDataProvider對象為Source創(chuàng )建Binding Binding bindingToArg1 = new Binding("MethodParameters[0]"){ Source = odp, BindsDirectlyToSource = true, //把UI接收到的數據寫(xiě)入其直接Source(即ObjectDataProvider)而不是Calculator對象 UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged //有更新立刻將值傳回Source};
Binding bindingToArg2 = new Binding("MethodParameters[1]"){ Source = odp, BindsDirectlyToSource = true, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged};//把ObjectDataProvider對象當做Source時(shí),這個(gè)對象本身就是數據,所以Path可以省略用.代替Binding bindingToResult = new Binding(".") { Source = odp };
this.textBoxArg1.SetBinding(TextBox.TextProperty, bindingToArg1);this.textBoxArg2.SetBinding(TextBox.TextProperty, bindingToArg2);this.textBoxResult.SetBinding(TextBox.TextProperty, bindingToResult);


6.3.12 使用Binding的RelativeSource

  當一個(gè)Binding有明確的數據來(lái)源時(shí),我們可以通過(guò)為Source或ElementName賦值的辦法進(jìn)行Binding

  有時(shí)候我們不確定Source對象叫什么,但知道它與Binding對象在UI布局上有相對關(guān)系,(比如控件自己關(guān)聯(lián)自己的某個(gè)數據、關(guān)聯(lián)自己某級容器的數據),這時(shí)我們就要使用RelativeSource屬性。

<Grid x:Name="g1" Background="Red" Margin="10"> <DockPanel x:Name="d1" Background="Orange" Margin="10"> <Grid x:Name="g2" Background="Yellow" Margin="10"> <DockPanel x:Name="d2" Background="LawnGreen" Margin="10"> <TextBox x:Name="textBox1" FontSize="24" Margin="10" Text="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Grid},AncestorLevel=1 },Path=Name}"/> </DockPanel> </Grid> </DockPanel></Grid>

//TextBox 綁定 等效代碼RelativeSource rs = new RelativeSource(RelativeSourceMode.FindAncestor); //引用元素綁定元素父鏈上級 //rs.AncestorLevel = 1; //以Binding目標控件為起點(diǎn)的層級偏移量 d2是1 g2是2 d1是3 g1是4rs.AncestorType = typeof(Grid); //源的類(lèi)型,不是則跳過(guò)Binding binding = new Binding("Name") { RelativeSource = rs };this.textBox1.SetBinding(TextBox.TextProperty, binding);

 


//顯示d1Text="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Dockpanel},AncestorLevel=2},Path=Name}"

  如果TextBox關(guān)聯(lián)自身的Name屬性,則代碼如下:

//顯示textBox1RelativeSource rs = new RelativeSource(RelativeSourceMode.Self);Binding binding = new Binding("Name") { RelativeSource = rs };this.textBox1.SetBinding(TextBox.TextProperty, binding);

6.4 Binding對數據的轉換與校驗

  Binding的作用是Source與Target之間的橋梁,當Binding兩端要求使用不同的數據類(lèi)型時(shí),我們可以為數據設置轉換器。

  ValidationRules屬性:數據有效性校驗

  Converter屬性:數據類(lèi)型轉換

6.4.1 Binding的數據校驗

   需要創(chuàng )建抽象類(lèi)ValidationRule的派生類(lèi)并實(shí)現它的Validate方法。

<StackPanel> <TextBox x:Name="textBox1" Margin="5" /> <Slider x:Name="slider1" Minimum="0" Maximum="100" Margin="5" /></StackPanel>

public class RangeValidationRule : ValidationRule{ //需要實(shí)現Validate 方法 public override ValidationResult Validate(object value, CultureInfo cultureInfo) { double d = 0; if (double.TryParse(value.ToString(), out d)) { if (d >= 0 && d <= 100) { return new ValidationResult(true, null); } }
return new ValidationResult(false, "Validation Failed"); }}

private void Window_Loaded(object sender, RoutedEventArgs e){ Binding binding = new Binding("Value") { Source = this.slider1 }; binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
RangeValidationRule rvr = new RangeValidationRule(); binding.ValidationRules.Add(rvr);
this.textBox1.SetBinding(TextBox.TextProperty, binding);}

  以Slider為源,TextBox為目標

  當TextBox輸入超出范圍時(shí),邊框會(huì )顯示為紅色

  Binding默認只校驗Target->Source,不校驗Source->Target的數據,如果想校驗需要設置 ValidatesOnTargetUpdated = true; 

6.4.2 Binding的數據轉換

   上面例子中,Slider控件作為Source(Path是Value屬性),TextBox控件作為T(mén)arget(目標屬性為T(mén)ext)。但Slider的Value是double,TextBox的Text是string,當Source端Path所關(guān)聯(lián)的數據與Target端目標屬性數據類(lèi)型不一致時(shí),我們可以添加數據轉換器。像double與string這種簡(jiǎn)單的轉換,WPF類(lèi)庫已經(jīng)做好了。

  手動(dòng)寫(xiě)Converter,方法是創(chuàng )建一個(gè)類(lèi)并讓這個(gè)類(lèi)實(shí)現IValueConverter接口。

public interface IValueConverter{ object Convert(object vale, Type outputType, object parameter, CultureInfo cultrue); object ConvertBack(object value, Type outputType, object parameter, CultureInfo culture);}

  當數據從Source到Target時(shí),Convert方法將被調用;反之,ConvertBack方法將被調用。

  實(shí)現過(guò)程如下:

<Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp1" mc:Ignorable="d" Title="MainWindow" Height="266" Width="300" >
<Window.Resources > <local:CategoryToSourceConverter x:Key="cts"/> <local:StateToNullableBoolConverter x:Key="stnb" /> </Window.Resources> <StackPanel Background="LightBlue" > <ListBox x:Name="listBoxPlane" Height="160" Margin="5" > <ListBox.ItemTemplate > <DataTemplate> <StackPanel Orientation="Horizontal"> <Image Width="20" Height="20" Source="{Binding Path=Category,Converter={StaticResource cts}}" /> <TextBlock Text="{Binding Path=Name}" Width="60" Margin="80,0" /> <CheckBox IsThreeState="True" IsChecked="{Binding Path=State,Converter={StaticResource stnb} }" /> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> <Button x:Name="buttonLoad" Content="Load" Height="25" Margin="5,0" Click="buttonLoad_Click" /> <Button x:Name="buttonSave" Content="Save" Height="25" Margin="5,5" Click="buttonSave_Click" /> </StackPanel></Window>

using System;using System.Collections.Generic;using System.Text;using System.Windows;using System.Windows.Data;using System.Globalization;using System.IO;
namespace WpfApp1{ public enum Category { Bomber, Fighter }
public enum State { Available, Locked, Unknown }
public class Plane { public Category Category { get; set; } public string Name { get; set; } public State State { get; set; } } /// <summary> /// MainWindow.xaml 的交互邏輯 /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); }
private void buttonLoad_Click(object sender, RoutedEventArgs e) { List<Plane> planeList = new List<Plane>() { new Plane() {Category =Category.Bomber,Name="B-1",State=State.Unknown }, new Plane() {Category=Category.Bomber,Name="B-2",State=State.Unknown }, new Plane() {Category=Category.Fighter,Name="F-22",State=State.Unknown }, new Plane() {Category=Category.Fighter,Name="Su-47",State=State.Unknown }, new Plane() {Category=Category.Bomber,Name="B-52",State=State.Unknown }, new Plane() {Category=Category.Fighter,Name="J-10",State=State.Unknown }, }; this.listBoxPlane.ItemsSource = planeList; }
private void buttonSave_Click(object sender, RoutedEventArgs e) { StringBuilder sb = new StringBuilder(); foreach(Plane p in listBoxPlane.Items) { sb.AppendLine(string.Format("Category={0},Name={1},State={2}", p.Category, p.Name, p.State)); } File.WriteAllText(@"D:\PlaneList.txt", sb.ToString()); } }
public class CategoryToSourceConverter:IValueConverter { public object Convert(object value,Type targerType,object parameter,CultureInfo cultrue) { Category c = (Category)value; switch (c) { case Category.Bomber: return @"\Bomber.png"; case Category.Fighter: return @"\Fighter.png"; default: return null; } } //不會(huì )被調用 public object ConvertBack(object value, Type targetType,object parameter,CultureInfo culture) { throw new NotImplementedException(); } }
public class StateToNullableBoolConverter:IValueConverter { //將State轉換為bool? public object Convert(object value,Type targetType,object parameter,CultureInfo culture) { State s = (State)value; switch(s) { case State.Locked: return false; case State.Available: return true; case State.Unknown: default: return null; } }     //將bool?轉換為State public object ConvertBack(object value,Type targetType,object parameter,CultureInfo culture) { bool? nb = (bool?)value; switch (nb) { case true: return State.Available; case false: return State.Locked; case null: default: return State.Unknown; } } }}

   =>  

Load后效果如上左,修改狀態(tài)后如上右,Save后如下

6.5 MultiBinding(多路Binding)

  有時(shí)UI顯示的信息由不止一個(gè)數據來(lái)源決定,這時(shí)就需要使用MultiBinding

 

轉載于:https://www.cnblogs.com/code1992/p/10250440.html

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Silverlight 4 數據綁定
Windows Presentation Foundation 數據綁定:第一部分
關(guān)于WPF的驗證
Silverlight實(shí)例教程 - Validation數據驗證基礎屬性和事件
“模板數據綁定”從XAML到代碼CODE
白話(huà) WPF/SL 綁定(Binding)
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久