简而言之,依赖属性就是一种可以自己没有值,并能通过使用Binding从数据源获得值(依赖在别人身上)的属性。而拥有依赖属性的对象被称为依赖对象。
与传统的CLR属性和面向对象思想相比依赖属性有很多新颖之处:
传统的.NET开发中,一个对象所占用的内存控件在调用new操作符进行实例化的时候就已经决定了,而WPF允许对象在被创建的时候并不包含用于储存数据的控件,只保留在需要时候能够获得默认值,借用其他对象数据或者分配空间的能力,这种对象就称为依赖对象,而它这种实时获取数据的能力则依靠依赖属性来实现,注意依赖对象不是数据产生的对象,而是具备获取其他对象的数据的能力的对象。
在WPF中,依赖对象的概念被DependencyObject
类所实现,依赖属性的概念被DependencyProperty
类所实现。DependencyObject具有GetValue和SetValue两个方法,DependencyProperty
必须以DependencyObject
为宿主,以这两个方法来进行写入与读取。
public class DependencyOobject:DispatcherObject{ public object GetValue(DependencyPropertyy dp)//从DependencyProperty对象获取数据 { .../// } public void SetValue(DependencyProperty dp,object value) { .../// } }
DependencyObject
是WPF系统中相当底层的一个基类,所有UI控件都是依赖对象。
例子:
<StackPanel Background="LightBlue"> <TextBox x:Name="textBox1" BorderBrush="Black" Margin="5"/> <TextBox x:Name="textBox2" BorderBrush="Black" Margin="5"/> <Button x:Name="btn" Content="OK" Click="btn_Click"/> </StackPanel>
public partial class MainWindow : Window { Student stu; public MainWindow() { InitializeComponent(); stu = new Student(); Binding binding = new Binding("Text") { Source = this.textBox1 }; stu.SetBinding(Student.NameProperty, binding); textBox2.SetBinding(TextBox.TextProperty, new Binding("Name") { Source = stu }); } private void btn_Click(object sender, RoutedEventArgs e) { MessageBox.Show(stu.Name); } } public class Student : DependencyObject { //注册依赖属性 public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name", typeof(string), typeof(Student)); //CLR包装属性 public string Name { get { return (string)GetValue(NameProperty); } set { SetValue(NameProperty, value); } } //SetBinding包装 public BindingExpressionBase SetBinding(DependencyProperty dp,BindingBase binding) { return BindingOperations.SetBinding(this, dp, binding); } }
简单总结下创建依赖对象,使用依赖属性的三部曲:
继承DependancyObject
类
在依赖对象内用DependancyProperty.Register
方法注册依赖属性
用CLR属性进行包装,结合依赖对象的SetValue
和GetValue
方法。
附加属性将的是一个属性本来不属于某个对象,但由于某种需求而被后来附加上。也就是把对象放入一个特定的环境后哦,对象才具有的属性。
Demo:
<StackPanel Background="LightBlue"> <Button x:Name="btn" Content="OK" Click="btn_Click"/> </StackPanel>
namespace MessagePump { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void btn_Click(object sender, RoutedEventArgs e) { Human human = new Human(); School.SetGrade(human, 6); int grade = School.GetGrade(human); MessageBox.Show(grade.ToString()); } } public class School : DependencyObject { //通过GetGrade、SetGrade,调用Human的SetValue和GetValue方法,存储依赖变量的值。 public static int GetGrade(DependencyObject obj) { return (int)obj.GetValue(GradeProperty); } public static void SetGrade(DependencyObject obj, int value) { obj.SetValue(GradeProperty, value); } // Using a DependencyProperty as the backing store for GradeProperty. This enables animation, styling, binding, etc...(注册依赖变量) public static readonly DependencyProperty GradeProperty = DependencyProperty.RegisterAttached("Grade", typeof(int), typeof(School), new PropertyMetadata(0)); } class Human : DependencyObject { } }