WPF-10: 属性-1

来自《深入浅出WPF》(刘铁猛)读书笔记

什么样的对象才能作为Binding的target以及Binding将把数据送往何处?

C#语言规定:对类有意义的字段和方法使用static关键字修饰,称为静态成员,通过类名加访问操作符“.”可以访问它们;对类的实例有意义的字段和方法不加static关键字,称为非静态成员或实例成员。

依赖属性:可以自己没有值,并能通过使用Binding从数据源获得值的属性。拥有依赖属性的对象被称为“依赖对象”。可以节省实例对内存的开销;属性值可以通过Binding依赖在其他对象上。

WPF允许对象在被创建的时候并不包含用于存储数据的空间(即字段所占用的空间),只保留在需要用到数据时能够获得默认值,借用其他对象的数据或实时分配空间的能力--这种对象就称为依赖对象(Dependency Object)而他这种实时获取数据的能力则依靠依赖属性(Dependency Property)来实现。WPF开发中,必须使用依赖对象作为依赖属性的宿主,使二者结合起来,才能形成完整的Binding目标被数据所驱动。

在WPF系统中,依赖对象的概念被DependencyObject类所实现,依赖属性的概念则有DependencyProperty类所实现。DependencyObject有GetValue和SetValue两个方法。

命名约定:成员变量的名字需要加上Property后缀以表明它是一个依赖属性。

依赖属性就是由public static readonly修饰的DependencyProperty实例,有没有包装器这个依赖属性都存在;同时,依赖属性的包装器(Wrapper)是一个CLR属性。

包装器的作用是以“实例属性”的形式向外界暴露依赖属性,这样,一个依赖属性才能成为数据源的一个Path。

public class Student: DependencyObject
{
    public static readonly DependencyProperty NameProperty= DependencyProperty.Register("Name",typeof(string),typeof(Student));
}

依赖属性首先是属性,尝试读取:

private void Button_Click(object sender,RoutedEventArgs e)
{
    Student stu=new Student();
    stu.SetValue(Student.NameProperty,this.textBox1.Text);
    textBox2.Text=(string)stu.GetValue(Student.NameProperty);
}

先创建一个Binding实例,让TextBox作为数据源对象并从其Text属性中获取数据;

Binding binding=new Binding("Text") {Source=textBox1};

使用BindingOperation类的setBinding方法指定将stu对象借助刚刚声明的Binding实例依赖在textBox1上:

stu=new Student();
BindingOperations.SetBinding(stu,Student.NameProperty,binding);

给依赖属性添加一个CRL属性外包装:

public class Student: DependencyObject
{
    //CRL property wraper
    public string Name
    {
        get {return (string)GetValue(NameProperty);}
        set {SetValue(NameProperty,value);}
    }
    public static readonly DependencyProperty NameProperty=DependencyProperty.Register("Name",typeof(string),typeof(Student));
}

尽管Student类没有实现INotifyPropertyChanged接口,当属性的值发生改变时与之关联的Binding对象依然可以得到通知,依赖属性默认带有这样的功能,天生就是合格的数据源。

添加SetBinding包装:

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

实例:把Student对象关联到TextBox1上,再把TextBox关联到Student对象上形成Binding链:

stu=new Student();
stu.SetBinding(Student.NameProperty,new Binding("Text"){Source=textBox1});
textBox1.SetBinding(TextBox.TextProperty,new Binding("Name"){Source=stu});

运行程序,当在TextBox1中输入字符时,textBox2就会同步显示,此时,Student对象的Name属性值也同步变化。

由snippet自动生成的代码中,DependencyProperty.Register使用的是4个参数的重载。依赖属性的DependencyMetadata只能通过Register方法的第4个参数赋值,而且一旦赋值就不能改变(DependencyMetadata是个只读属性),如果想用新的PropertyMetadata替换这个默认的Metadta,需要使用DependencyProperty.OverrideMetadata方法。





猜你喜欢

转载自blog.csdn.net/huan_126/article/details/80093490