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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Binding的使用梳理

發布時間:2023/12/16 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Binding的使用梳理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.Binding的基礎概念
將Source的數據傳遞給Target,或者Target的數據傳遞給Source

2.Binding最簡單的綁定
創建一個普通的Student類,包含一個Name屬性,當作Source
讓這個類繼承INotifyPropertyChanged接口,實現該接口,即聲明
一個PropertyChangedEventHandler事件

public class Student:INotifyPropertyChanged {private string name;public string Name{get { return name; }set { name = value;if (PropertyChanged!=null){this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Name"));}}}public event PropertyChangedEventHandler PropertyChanged;`在這里插入代碼片`}事件信息參數為要修改的Name屬性。 然后在XAML中聲明一個TextBox與Button,TextBox作為Target,Button修改Source的Name。可以在C#中做綁定```csharp this.text1.SetBinding(TextBox.TextProperty,new Binding("Name") { Source=stu});

也可以在XAML中做綁定,XAML語言是不能直接訪問對象的,只能通過ElementName=sourceName,即通過設置ElementName,對象名字來訪問對象

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

XAML中進行綁定最好是簡單的綁定,只有Source Path 這種是比較合適的,當涉及到數據校驗或者數據轉換的時候,需要在C#的代碼中實現較為合適。
可以看出的是XAML中進行Binding的方式是對某一屬性使用擴展方法進行賦值,賦值的內容為"{Binding Path= , ElementName =,…}"

3.沒有Path的綁定
Source本身就是一個值的時候,即Source為Path的時候可以省略掉Path

<StackPanel.Resources><sys:String x:Key="myString">菩提本無樹,明鏡亦非臺。本來無一物,何處惹塵埃。</sys:String></StackPanel.Resources><TextBlock x:Name="textBlock1" TextWrapping="Wrap" Text="{Binding Source={StaticResource ResourceKey=myString}}" FontSize="16" Margin="5"/></StackPanel>

對應的C#綁定代碼為
string mystring = “菩提本無樹,明鏡亦非臺。本來無一物,何處惹塵埃。”;
this.textBlock1.SetBinding(TextBlock.TextProperty, new Binding(".") { Source = mystring });

4.作為Source的情況,當Source指定好之后,Path就可以比較簡單的確認了,無論是Source本身還是其中的某一屬性。
(1)普通的類(注意要實現INotifyPropertyChanged接口來通知binding數據更新),或者普通的控件都可以作為Source
(2)DataContext:所有的控件都有這個屬性,當沒有給這個屬性賦值的時候,會根據UI樹向上尋找有賦該值的控件,然后借用其值(依賴屬性的定義)
先聲明一個學生類

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

注意不要聲明字段,在XAML中為DatatContext中設置的時候讀取不到字段。
XAML中設置TextBox與Student中類的屬性進行綁定

<StackPanel Background="LightBlue"><StackPanel.DataContext><local:Student Name="Tim" Age="28" Id="6"/></StackPanel.DataContext><Grid><StackPanel><TextBox Text="{Binding Path=Name}" Margin="5"/><TextBox Text="{Binding Path=Id}" Margin="5"/><TextBox Text="{Binding Path=Age}" Margin="5"/></StackPanel></Grid></StackPanel>

這時候是沒有指明Source的,聲明綁定過后,會在UI樹上尋找有該屬性的控件然后綁定該屬性的值。
例如:第一個TextBox 綁定的 Path是Name,這時候就會在UI樹上找那個控件有對應的值,這時候發現 StackPanel中的DataContext有該值,則進行綁定。
另外比較特殊的是,如果Source即是Path則 可以直接寫作Text="{Binding}" 這種既無Source也無Path的形式。
(3)關于鏈表式控件的綁定
鏈表式控件,可以像普通的綁定那樣進行一對一的綁定。
并且鏈表式控件都有ItemsSource,該屬性接收一個IEnumerable接口派送類的對象。并且鏈表式控件具有條目容器。當使用 ItemsSource接收數據時,就會為每個數據都準備條目容器,當作數據外衣使用。
做一個簡單的例子:
XAML中聲明一個鏈表式控件:

在C#中聲明一個List,并且與listStudent進行綁定

List<Student> students = new List<Student>{new Student(){ Id=0,Age=29,Name="tim"},new Student(){ Id=1,Age=26,Name="tom"},new Student(){ Id=2,Age=25,Name="lucy"},new Student(){ Id=3,Age=24,Name="jerry"},new Student(){ Id=4,Age=23,Name="nancy"},new Student(){ Id=5,Age=22,Name="mike"},};this.listStudent.ItemsSource = students;this.listStudent.DisplayMemberPath = "Name";

唯一的缺陷是這個條目容器是默認值的,只能顯示一個值,當要同時顯示Id,Age,Name的時候就需要自己設計條目容器ItemTemplate,DataTemplate

<ListBox x:Name="listStudent" Height="300" Width="500"><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>

說完鏈表式控件作為Target使用的過程,可以作為鏈表式控件的Source的是IEnumrable的派送類。可以看到比較常用的場景有:
①ADO.NET讀取的數據庫的數據
ADO.NET類,常用來與數據庫做交互使用。常見的工作是從數據庫中讀取數據到DataTable中,在把DataTable中的數據顯示在UI上。
比較特殊的是DataTable不能直接綁定在鏈表式控件的ItemsSource上。一般是
DataTable dt=this.Load();
this.listName.DisplayMemberPath=“Name”;
this.listName.ItemsSource=dt.DefaultView;

DataTable的DefaultView中的值是DataView類型的對象實現了IEnumerable接口
為了更好的展示就使用ListView控件來展示,手動的設置條目容器的樣式。XAML代碼如下:

<ListView x:Name="listViewName" Height="130" Margin="5"><ListView.View><GridView><GridViewColumn Header="TileName" Width="60" DisplayMemberBinding="{Binding Path=pathName}"/></GridView></ListView.View></ListView>

條目容器的設置是設置相關的View屬性。View屬性的值是GridView。GridView的屬性值是Column。綁定的Target.Property也變成了DisplayMemberBinding。
綁定的Source還是ItemsSource。
已知的是DataTable是不能直接賦給ItemsSource的,但是可以賦給控件的DataContext,然后直接進行沒有Source的綁定。
②XML數據
主要是XML數據讀取轉換成IEnumerable派送類這塊,后續綁定和前面說的鏈表式控件的綁定過程一樣。
使用的是XmlDataProvider類。

XmlDocument doc =new XmlDocument(); doc.Load(@"Path");XmlProvider xdp=new XmlProvider(); xdp.Document=doc;xdp.XPath=@"/tagName1/tagName2"this.listViewName.DataContext=xdp; this.listViewName.SetBinding(ListViewItemsSourceProperty,new Binding());

設置條目容器的樣式的時候的展示內容,在Xaml中需要注意的是,如果是Xml的Attribute要加@,不加的是子級元素

<GridViewColumn Header="TileName" Width="60" DisplayMemberBinding="{Binding XPath=@AttributepathName}"/> <GridViewColumn Header="TileName" Width="60" DisplayMemberBinding="{Binding XPath=pathName}"/>

XML語言是很方便展示樹形結構的數據。
③前面兩種都可以通過 Linq語言直接處理之后變為IEnumerable類型的數據,直接賦給ItemsSource屬性。
this,listViewName.ItemsSource= from list1 in listName Where … select stu;

關于數據庫文件與Xml文件通過Linq處理的,單獨列章分析。

5.有時候要綁定的Source是別人類庫的東西,或者是通過別人封裝好的方法的返回值,這時候就可以通過ObjectDataProvider來包裝作為Binding源的數據對象。

ObjectDataProvider包裝過程 ObjectDataProvider odp = new ObjectDataProvider(); odp.ObjectInstance = new ClassName(); odp.MethodName = "MethodName"; odp.MethodParameters.Add("Arg[0]"); odp.MethodParameters.Add("Arg[1]");

Demo:
設置一個Calculator類做加法運算

class Calculator {public string Add(string arg1, string arg2) {double x;double y;double z;if (double.TryParse(arg1,out x)&&double.TryParse(arg2,out y)){z = x + y;return z.ToString();}return "Input error";}}

使用ObjectDataProvider進行封裝

ObjectDataProvider odp = new ObjectDataProvider(); odp.ObjectInstance = new Calculator(); odp.MethodName = "Add"; odp.MethodParameters.Add("0"); odp.MethodParameters.Add("0");

設置Binding:

<StackPanel Background="LightBlue"><TextBox x:Name="textArg1" Margin="5"/><TextBox x:Name="textArg2" Margin="5"/><TextBox x:Name="textArgResult" Margin="5"/></StackPanel>

C#中運行就調用的方法:

private void SetBinding() {ObjectDataProvider odp = new ObjectDataProvider();odp.ObjectInstance = new Calculator();odp.MethodName = "Add";odp.MethodParameters.Add("0");odp.MethodParameters.Add("0");Binding bindingToArg1 = new Binding("MethodParameters[0]") {Source = odp,BindsDirectlyToSource=true,UpdateSourceTrigger=UpdateSourceTrigger.PropertyChanged};Binding bindingToArg2 = new Binding("MethodParameters[1]"){Source = odp,BindsDirectlyToSource = true,UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged};Binding bindingToResult = new Binding(".") { Source = odp };this.textArg1.SetBinding(TextBox.TextProperty,bindingToArg1);this.textArg2.SetBinding(TextBox.TextProperty, bindingToArg2);this.textArgResult.SetBinding(TextBox.TextProperty, bindingToResult);}

6.Source為RelativeSource
先初始化該類

RelativeSource rs=new RelativeSource(RelativeSource.Mode....) Binding binding=new Binding("Name"){RelativeSource=rs}; this.UIName.Setbingding(Property,binding);

初始化的Mode,為枚舉類型,分別為PreviousData,TemplatedParent,Self和FindAncestor,前三個是創建RelativeSource實例,把實例的Mode是指為相應的值,然后返回這個實例。
Demo:

<StackPanel x:Name="s1" Background="LightBlue"><Grid x:Name="g1"><StackPanel x:Name="s2"><DockPanel x:Name="d1"><TextBox x:Name="t1"></TextBox></DockPanel></StackPanel></Grid></StackPanel> 若為FindAncestor則還要設置AncestorLevel和AncesType RelativeSource rs = new RelativeSource(RelativeSourceMode.FindAncestor); rs.AncestorLevel = 1; rs.AncestorType = typeof(Grid); this.t1.SetBinding(TextBox.TextProperty, new Binding("Name") { RelativeSource=rs});

如果是其他三個則可以直接使用:

RelativeSource rs = new RelativeSource(RelativeSourceMode.Self); this.t1.SetBinding(TextBox.TextProperty, new Binding("Name") { RelativeSource=rs});

7.Binding過程的數據校驗
Binding數據校驗主要是使用Binding.Validation.Add(ValidationRule)
參數為實現了ValidationRule的派生類。
Demo:

class RangValidation : ValidationRule {public override ValidationResult Validate(object value, CultureInfo cultureInfo) {double d;if (double.TryParse(value.ToString(),out d)){if (d>0&&d<100){return new ValidationResult(true, null);}}return new ValidationResult(false, "Data is error");}} private void SetBinding() {RangValidation rang = new RangValidation();rang.ValidatesOnTargetUpdated = true;Binding binding = new Binding();binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;binding.ValidationRules.Add(rang);binding.Source = this.slider1;binding.Path = new PropertyPath("Value");this.text1.SetBinding(TextBox.TextProperty, binding);}

如果要在UI樹上通知校驗后的信息,只需要把

Binding.ValidationOnNotifyDataErrors=true

然后在需要顯示的UI控件上做路由偵聽。(路由事件的時候具體寫)

8.Binding數據的轉換
數據的傳輸很多時候要面對的問題是數據類型。
當Source Path與Target的類型不一樣的時候,如slider的Value是Double,而Text是String。
一些簡單的數據轉換Binding會自動實現,像是Double->String。
遇到復雜的情況需要自己實現 Data Converter
即創建一個類實現IValueConverter接口的類

class DataConverterDemo : IValueConverter {public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {//轉換value值,針對value值的不同返回想要的類型ClassName c1=(ClassName)value;switch (cl){case A:return oneTypeClass;default:break; }}public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {ClassName c1=(ClassName)value;switch (cl){case A:return oneTypeClass;default:break; }}} }

從Source->Target時調用Convert
從Target->Source時調用ConvertBack
使用的時候直接設置:

Binding.Converter=dataConcerter

9.MutilBinding

MutilBinding mb=new MutilBinding(); mb.MutilBindings.Add(new Binding());

另外這種多個Source綁定一個Target的數據類型轉換器Data Converter要實現的是IMutilValueConverter接口,實現的方法同IValueConverter差不多,不過傳遞的第一個參數為object[] values。
MutilBindings.Add添加的時候是順序敏感的。

整理《深入淺出WPF》

總結

以上是生活随笔為你收集整理的Binding的使用梳理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。