【WPF】数据绑定- Binding类


学习之前要具备的知识点

1、依赖属性、依赖对象、xaml标记扩展

https://docs.microsoft.com/en-us/dotnet/desktop/wpf/data/data-binding-overview?view=netframeworkdesktop-4.8

数据绑定基本概念

不论要绑定什么元素,也不论数据源是什么性质,每个绑定都始终遵循下图所示的模型。

Diagram that shows the basic data binding model.

形象地讲,Binding就像一个盒子,盒子里装了一些机关用于过滤和控制数据,盒子两端各接着一根管子,管子是由管壳和管芯构成的,看上去就像下面的图:

【WPF】数据绑定- Binding类

 

当脑子里有了这样一个形象之后,遵循下面的步骤就OK了:

  1. Source:确定哪个对象作为数据源,5种数据源
  2. Target:确定哪个对象作为目标
  3. Binding:声明一个Binding实例,binding看成中间有类型转换器typeconvert
  4. 把一根管子接到Source上并把管芯插在Source的Path(属性或索引,不能是公有字段、不能是私有信息;xmldom是xpath)上
  5. 把另一根管子接到Target上并把管芯插在Target的依赖属性上

如果有必要,可以在3与4之间设置Binding的“关卡”们。其实,第3步之后的顺序不是固定的,只是这个步骤比较好记——一概向右连接。所得结果看上去是这样:

 【WPF】数据绑定- Binding类

 

 

通常情况下,每个绑定具有四个组件:

  • 绑定目标对象。
  • 目标属性。目标属性必须为依赖属性。 大多数 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) 数据绑定支持以下绑定源类型:

更改通知

如果使用的是 OneWayTwoWay 绑定(因为当绑定源属性动态更改时,希望自己的 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

(0)
上一篇 2022年7月10日
下一篇 2022年7月10日

相关推荐

发表回复

登录后才能评论