《深入浅出WPF》学习笔记

第6章 深入浅出话Binding

6.2 Binding基础

  如果把Binding比作数据的桥梁,那么它的两端分别是Binding的(Source)和目标(Target)。一般源是逻辑层对象,目标是UI层控件对象.

  我们可以控制源与目标是双向通行还是单向,还可以控制对数据放行的时机,还可以设置“关卡”转换数据类型或校验数据的正确性。

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

  Path:如上所示,一个对象有多个属性,UI上关心哪个属性值的变化呢?这个属性就称为Binding的路径(Path)

  PropertyChanged:让属性具备通知Binding值已变化的能力。作为数据源的类实现INotifyPropertyChanged接口。

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

 

  Binding的过程:

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

  主要是 源、路径、设置绑定

  

  实际工作中,实施Binding的代码可能与上面不太一样,因为TextBox这类UI元素的基类FramewordElement对BindingOperation.SetBinding(...)方法进行了封装,封装的结果也叫SetBinding,只是参数列表发送了变化  

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

  借助Binding类的构造器及C#3.0的对象初始化器语法简化上述代码

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

 

6.3 Binding的源与路径

  源:只要是一个对象,并行通过属性(Property)公开自己的数据,它就能作为Binding的源

     如果想让作为Binding源的对象具有自动通知Binding属性已改变的能力,就需要让类实现InotifyPropertyChanged接口并在熟悉的set语句中激发PropertyChanged事件。

       除了对象作为数据源外,还可以有很多选择,控件自己或自己的容器或子集元素、集合作为ItemsControl的数据源、XML作为TreeView或Menu的数据源、把多个控件关联到一个“数据制高点”上、甚至干脆不给Binding指定数据源,让它自己去找

 

6.3.1 把控件作为Binding源与Binding标记拓展

  大多数情况下Binding的源是逻辑层对象,但有时候为了让UI元素产生联动效果也会使用Binding在控件间建立关联。

  如把TextBox的Text属性关联在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>

  WPF学习笔记

  

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

  与下面C#代码等价,且上面Path=可以省略

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

  

  wpf数据绑定SourceElementName的区别

  • Source 用于指定数据源为后台数据对象集合

  • ElementName 用于指定“数据源”为界面上某个控件的某个属性

 

  注意:

  在C#代码中可以访问XAML代码中声明的变量,但XAML代码中无法访问C#代码中声明的变量。

  因此,要想在XAML中建立UI元素与逻辑层对象的Binding还要颇费些周折,把逻辑层对象声明为XAML代码中的资源(Resource),见资源一章。

 

6.3.2 控制Bangding的方向及数据更新

  有时候数据只需要展示给用户、不允许用户修改,这时候可以把Binding模式更改为从源向目标的单向沟通 (源→目标:OneWay

  Mode:属性Mode控制绑定方向。BindingMode类型的枚举值:TwoWay、OneWay、OnTime、OneWayToSource和Default。    

  • TwoWay  源↔目标  无论是目标属性还是源属性,只要发生了更改,TwoWay 就会更新目标属性或源属性。

  • OneWay  源→目标  仅当源属性发生更改时更新目标属性。

  • OneTime 仅当应用程序启动时或 DataContext 进行更改时更新目标属性。

  • OneWayToSource  目标→源  在目标属性更改时更新源属性。

  • Default 使用目标属性的默认 Mode 值。(这里的Default指的是Binding的模式会根据目标是实际情况来确定,如果是可以编辑的(TextBox的Text属性),Default就采用双向模式。如果是TextBlock,不可编辑,就使用单向模式。

 

  上述Slider示例中,在TextBox输入一个值,然后按Tab键(TextBox丢失焦点),Slider的手柄会自动跳到相应的位置。

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

 

 

  为什么一定要丢失焦点后Slider的值才变呢?

  UpdateSourceTrigger:属性控制值改变时机。枚举值PropertyChanged、LostFocus、Explicit和Default

Explicit,源不会更新除非你手动来操作
LostFocus,一旦目标控件失去焦点,源就会被更新。
PropertyChanged,一旦绑定的属性值改变,源会立即更新。
View Code

相关文章: