对应WPF编程宝典 第八章 第十九章 第二十章
本笔记仅供自己查漏补缺使用,在记录的过程中可能会侧重How而忽略Why和What。

基础绑定

首先来看下绑定的实现类 Binding类,在PresentationFramework程序集的 System.Windows.Data命名空间下 image.png

其中 Mode、Path、ElementName、Source、Converter 是我们最常用的参数,在XAML中可以直接赋值。

Path

指向目标属性的路径,可以是属性的名称,也可以是属性的属性,也可以包含属性的索引器。
如果希望引用附加属性,那么需要使用”()”封装属性的名称。比如使用(Grid.Row)来绑定元素的行号绑定到附加属性。
该属性只需要指向属性或者依赖属性都可以,但是要注意对应属性的访问修饰符。

Source

Source是指绑定的属性的来源的对象,提供对象的数据,可以通过多种方式设置。

1.使用ElementName绑定到文档中的其他元素时

可以使用ElementName属性指定对象的名称。

  1. <TextBox Text="Binding ElementNamme=Window,Path=Title"/>

2.使用Source绑定到静态对象

可以使用Source属性指向目标

  1. <TextBox Text="{Binding Source={x:Static System.IconFontFamily},Path=Source}"

这个表达式将静态属性SystemFonts.IconFontFamily提供的Fontmaily对象设置为了Binding.Source,并且将Path设置为FontFamily.Source,从而得到了字体家族的名称。

3.使用RelativeSource绑定到父元素

RelativeSource的Mode属性具有多种枚举,总计4种模式

名称 说明
Self 绑定到自身元素
FindAncetor 绑定到父元素。
搭配AncetorType与AncetorLevel使用
PreviousData 列表项中可用,绑定列表种的前一个数据项。
TemplateParent 绑定到应用模板的元素。仅当位于模板内部时才能使用。

4.缺省Source设置,自动获取DataContext

当表达式中省略了数据源信息时,WPF会检查元素的DataContext属性,如果为Null会继续在元素树向上寻找第一个部位Null的DataContext。
这是因为DataContext是依赖属性,当自身为空时会顺着树结构读取父元素的DataContext属性。

Mode

在设置Binding的时候可用为其设置BindingMode,该属性为枚举值。

OneWay 数据源发生变化时更新目标
TwoWay 数据源发生变化时更新目标,目标发生变化时更新数据源
OneTime 根据绑定时的源属性值设置目标属性。 确定原属性不会变化时可用使用,可用降低开销。
OneWayToSource 目标发生变化时更新数据源 提供数值的属性必须是依赖属性。
Default 取决于依赖属性的默认值。 取决于依赖属性中的元数据。FrameworkProperyMetadata.BindsTwoWayByDefault
标识。

绑定更新&绑定延迟

绑定更新

在TwoWay和OneWayToSource的绑定模式中,可通过UpdateSourceTrigger属性控制触发更新目标属性的时机。

  • PropertyChanged 属性变更时立即更新
  • LostFocus 当属性发生变化 且 目标丢失焦点时更新
  • Explict 手动调用BindingExpression.UpdateSource()时才更新
  • Default 根据目标属性的元数据确定行为,大多数属性默认是PopertyChanged,TextBox.Text是LostFocus

    绑定延迟

    可以为绑定设置Delay属性,避免过分频繁的触发属性变更操作。
    这里的500单位为毫秒,会在用户输入停止后500毫秒触发更新。

    1. <TextBox Text="{Binding Path=FontSize,Delay=500}"

    变更通知

    依赖属性

    实现变更通知的方法有多种多样,其中一种是使用依赖属性,依赖属性天生支持变更通知,但这并非最自然的方式。

    INotifyPropertyChanged接口

    手动实现

    1. class NotifyObject : INotifyPropertyChanged
    2. {
    3. private int number;
    4. public int Number
    5. {
    6. get { return number; }
    7. set { number = value; OnPropertyChanged("Number"); }
    8. }
    9. private string text;
    10. public string Text
    11. {
    12. get { return text; }
    13. set { text = value; OnPropertyChanged("Text"); }
    14. }
    15. public event PropertyChangedEventHandler PropertyChanged;
    16. protected void OnPropertyChanged(string propertyName = "")
    17. {
    18. PropertyChangedEventHandler handler = PropertyChanged;
    19. if (handler != null)
    20. {
    21. handler(this, new PropertyChangedEventArgs(propertyName));
    22. }
    23. }
    24. }

    使用Fody在编译时自动实现

  1. 安装 PropertyChanged.Fody库
  2. 为目标类添加 [ImplementPropertyChanged] 注解,编译后的代码会自动实现INotifyPropertyChanged ```csharp  [ImplementPropertyChanged]   public class Person   {

    public string GivenNames { get; set; }     public string FamilyName { get; set; }

    public string FullName => string.Format(“{0} {1}”, GivenNames, FamilyName);   }

  1. 实际上各种Mvvm框架中也有自己的实现INotifyPropertyChanged方法,比如Prism是通过`SetProperty(ref xxx,Value)` 来代替Set器中的内容实现的,开发中需要结合自己的情况决定采用哪种方式。
  2. <a name="eaPd7"></a>
  3. ### 检索BindingExpression.UpdateTarget()
  4. 最笨拙的方法
  5. 1. 通过FrameworkElement.GetBindingExpression() 获取绑定。
  6. 1. 调用BindingExpression.UpdateTarget()方法来触发更新。
  7. <a name="EMTjI"></a>
  8. ## 数据验证
  9. 讲道理这东西我没用过....
  10. <a name="3rFqc"></a>
  11. ## NULL值绑定
  12. WPF对于NULL值的默认处理是 不显示任何内容。<br />可以通过TargetNullValue属性改变WPFNull值的处理方式,如下,当绑定的数据源为Null时,将显示在TargetNullValue中提供的值。
  13. ```xml
  14. Text ="{Binding Path=Description, TargetNullValue=No Description Provided}"

数据转换

值转换器

之转换器是实现了IValueConverter接口的类,原理如下
image.png

通常是在Window/Usercontrol 的Resourse中创建一个转换器。在创建转换器的时候还可以为转换器中的public属性赋值。

image.png
image.png

多属性转换器

多属性转换器需要使用IMultiValueConverter,在绑定的时候也要使用MultBinding,如下
image.png
需要注意的是 在Converter中拿到的是Values[] 数组,顺序是按照Binding中传入的顺序排列

StringFormat属性

通过设置Binding.StringFormat 对文本格式的数据进行转换。
在使用StringFormat的时候要注意下以下几点。

  • 当StringFormat 以空格 或者没有其他值开头时,需要使用”{}”在最前面进行转义。如StringFormat={}{0:C}

  • StringFormat同转换器一样,支持多个属性。写法如下

    1. <TextBlock>
    2. <TextBlock.Text>
    3. <MultiBinding stringFormat="{1},{0}"]>
    4. <Binding Path="FirstName"></Binding>
    5. <Binding Path="LastName"></Binding>
    6. </MultiBinding>
    7. </TextBlock.Text>
    8. </TextBlock>

常见转义如下。

image.png