学习之前要具备的知识点
数据绑定基本概念
不论要绑定什么元素,也不论数据源是什么性质,每个绑定都始终遵循下图所示的模型。
形象地讲,Binding就像一个盒子,盒子里装了一些机关用于过滤和控制数据,盒子两端各接着一根管子,管子是由管壳和管芯构成的,看上去就像下面的图:
当脑子里有了这样一个形象之后,遵循下面的步骤就OK了:
- Source:确定哪个对象作为数据源,5种数据源
- Target:确定哪个对象作为目标
- Binding:声明一个Binding实例,binding看成中间有类型转换器typeconvert
- 把一根管子接到Source上并把管芯插在Source的Path(属性或索引,不能是公有字段、不能是私有信息;xmldom是xpath)上
- 把另一根管子接到Target上并把管芯插在Target的依赖属性上
如果有必要,可以在3与4之间设置Binding的“关卡”们。其实,第3步之后的顺序不是固定的,只是这个步骤比较好记——一概向右连接。所得结果看上去是这样:
通常情况下,每个绑定具有四个组件:
- 绑定目标对象。
- 目标属性。目标属性必须为依赖属性。 大多数 UIElement 属性都是依赖属性,而大多数依赖属性(只读属性除外)默认支持数据绑定。 (仅派生自 DependencyObject 的类型才能定义依赖属性;所有 UIElement 类型都派生自
DependencyObject
。) - 绑定源。绑定源可以是.NET 对象、 XMLDom 形式的数据、 UIElement、任何列表对象、ADO.NET对象 或 Web 服务对象,或包含 XML 数据的 XmlNode。 有关详细信息,请参阅绑定源概述。
- 指向绑定源中要使用的值的路径(PropertyPath或者xpath)。
D.P.的全称是“Dependency Property”,直译过来就是“依赖式属性”,意思是说它自己本身是没有值的,它的值是“依赖”在其它对象的属性值上、通过Binding的传递和转换而得来的。表现在例子里,它就是Target上的被数据所驱动的联动属性了!
这里是等价的C#代码,我把它写在了Window1的构造函数里:
public Window1() { InitializeComponent(); // 1. 我打算用slider1作为Source // 2. 我打算用textBox1作为Target Binding binding = new Binding(); binding.Source = this.slider1; //默认源是 binding.Path = new PropertyPath("Value"); //Value是属性名称 Path不能xml类,xmldom要用xpath this.textBox1.SetBinding(TextBox.TextProperty, binding); }
有意思的是,Source端的操作,接管子和插管芯分两步,而Target端却是在SetBinding方法中一步完成。注意啦,TextBox.TextProperty就是一个Dependency Property的庐山真面目!
上面的代码稍有简化的余地,那就是把Path的设定转移到Binding的构造中去:
public Window1() { InitializeComponent(); // 1. 我打算用slider1作为Source // 2. 我打算用textBox1作为Target Binding binding = new Binding("Value"); binding.Source = this.slider1;//默认源是DataContent this.textBox1.SetBinding(TextBox.TextProperty, binding); }
我们还可以为binding设些“关卡”:
public Window1() { InitializeComponent(); // 1. 我打算用slider1作为Source // 2. 我打算用textBox1作为Target Binding binding = new Binding("Value"); binding.Source = this.slider1;//默认源是DataContent binding.Mode = BindingMode.TwoWay;//4种依赖源模式 binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;//4种方式更新源 this.textBox1.SetBinding(TextBox.TextProperty, binding); }
绑定源类型
Windows Presentation Foundation (WPF) 数据绑定支持以下绑定源类型:
-
.NET 公共语言运行时 (CLR) 对象
可以绑定到任何公共语言运行时 (CLR) 对象的公共属性、子属性和索引器。 绑定引擎使用 CLR 反射来获取属性值。 实现了 ICustomTypeDescriptor 或具有已注册 TypeDescriptionProvider 的对象也可以使用绑定引擎。
有关如何实现可用作绑定源的类的详细信息,请参阅本文后面的在对象上实现绑定源。
-
动态对象
可以绑定到对象的可用属性和索引器,该对象实现 IDynamicMetaObjectProvider 接口。 如果可以访问代码中的成员,则可以绑定到该成员。 例如,如果动态对象使用户可以通过
someObjet.AProperty
访问代码中的成员,则可以通过将绑定路径设置为AProperty
来绑定到该成员。 -
ADO.NET 对象
可以绑定到 ADO.NET 对象,例如 DataTable。 ADO.NET DataView 实现 IBindingList 接口,该接口提供绑定引擎侦听的更改通知。
-
XML 对象
可以绑定到 XmlNode、XmlDocument 或 XmlElement,并对其运行
XPath
查询。 访问 XML 数据(标记中的绑定源)的便捷方法是使用 XmlDataProvider 对象。 有关详细信息,请参阅使用 XMLDataProvider 和 XPath 查询绑定到 XML 数据 (.NET Framework)。使用 LINQ to XML,还可以绑定到 XElement 或 XDocument,或者绑定到对这些类型的对象运行查询而得到的结果。 使用 LINQ to XML 访问 XML 数据(标记中的绑定源)的便捷方法是使用 ObjectDataProvider 对象。 有关详细信息,请参阅绑定到 XDocument、XElement 或 LINQ for XML 查询结果 (.NET Framework)。
-
可以绑定到任何 DependencyObject 的依赖属性。 有关示例,请参阅绑定两个控件的属性 (.NET Framework)。
更改通知
如果使用的是 OneWay 或 TwoWay 绑定(因为当绑定源属性动态更改时,希望自己的 UI 随之更新),必须实现适当的属性更改通知机制。 对于 CLR 或动态类,建议的机制是实现 INotifyPropertyChanged 接口。 有关详细信息,请参阅实现属性更改通知。
如果创建的 CLR 对象未实现 INotifyPropertyChanged,必须安排自己的通知系统,才能确保绑定中所用的数据保持最新状态。 可以通过支持要更改通知的每个属性的 PropertyChanged
模式来提供更改通知。 若要支持此模式,请为每个属性定义一个 PropertyNameChanged 事件,其中 PropertyName 是属性的名称。 每次更改属性时都会引发该事件。
如果绑定源实现了其中一个通知机制,将会自动进行目标更新。 如果绑定源由于某种原因未提供正确的属性更改通知,则可以选择使用 UpdateTarget 方法来显式更新目标属性。
自定义数据源
自定义数据源:
在我们项目组日常的工作中,经常需要自己写一个类,并且拿它的实例当作数据源。怎样才能让一个类成为“合格的”数据源呢?
要诀就是:
为这个类定义一些Property,相当于为Binding提供Path
让这个类实现INotifyPropertyChanged接口。实现这个接口的目的是当Source的属性值改变后通知Binding(不然人家怎么知道源头的数据变了并进行联动协同呢?),好让Binding把数据传输给Target——本质上还是使用事件机制来做,只是掩盖在底层、不用程序员去写event handler了。
public class MyMarkupExtension : MarkupExtension, INotifyPropertyChanged { public MyMarkupExtension() { } private string firstStr; public String FirstStr { get => firstStr; set { firstStr = value; NotifyPropertyChanged(); } } public MyMarkupExtension(string firstStr) { } private void NotifyPropertyChanged([CallerMemberName] String propertyName = "") { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public String SecondStr { get; set; } public event PropertyChangedEventHandler? PropertyChanged; public override object ProvideValue(IServiceProvider serviceProvider) { return FirstStr + " " + SecondStr; } }
应用
Binding binding = new Binding(); binding.Source = myMarkupExtension; binding.Path = new PropertyPath("FirstStr"); teb.SetBinding(TextBlock.TextProperty, binding);
OK,此时,你可以尝试使用MyMarkupExtension类的实例作为数据源了!MyMarkupExtension 同时也解除扩展标记接口,因此也是一个自定义扩展标记。
解除数据绑定
原理:利用依赖对象提供的ClearValue()方法解除绑定
BindingOperations类包装依赖对象的ClearValue()方法后提供了.ClearBinding()/ClearAllBinding(),用法如下:
BindingOperations.ClearBinding(lbl, Label.FontSizeProperty);//解除lable元素的FontSizeProperty依赖属性的绑定 BindingOperations.ClearAllBindings(lbl);//解除lable元素的所有属性的绑定
在数据绑定中,绑定源对象是指用户从其获取数据的对象。 本文讨论可以用作绑定源的对象类型,如 .NET CLR 对象、XML 和 DependencyObject 对象。
PropertyPath类用在对象的数据绑定中(Data Binding)
数据绑定是一个WPF特性,因此你可以把任何依赖对象属性绑定到目标值。然而,数据绑定的源不是必须是依赖属性;它可以是任何属性类型,只要这个属性类型能被应用程序数据提供器识别就可以。PropertyPath特别是用于ObjectDataProvider,对象数据提供器用来从公共运行时(CLR)对象和它们的属性中获取绑定源。
记住,XML数据绑定不适用PropertyPath,因为它在Binding中不用Path,而是XPath。你可以用XPath和有效的XPath语法指向数据的XML DOM。XPath也是被规定为字符串,但是不在这里讲解。
理解数据绑定中的属性路径的关键是你能把绑定定位到它的属性值,或者你可以绑定到列表或者集合属性。如果你要绑定到集合,比如绑定一个ListBox,ListBox会根据集合中项目的数量自动进行扩展。
绑定对象数据提供器ObjectDataProvider绑定方法
使用ObjectDataProvider对象作为Binding的Source
语法
<object Path="[index1,index2...]" ... /> <object Path="propertyName[index,index2...]" ... /> <Rectangle Fill="{Binding ColorGrid[20,30].SolidColorBrushResult}" ... /> <Binding Path="propertyName.propertyName2" ... /> <object Path="propertyName/propertyNameX" ... /> <object Path="[index1,index2...]" ... /> <object Path="propertyName[index,index2...]" ... />
详细请点击
原创文章,作者:6024010,如若转载,请注明出处:https://blog.ytso.com/273321.html