CLR属性、依赖属性与附加属性(WPF)
2011-12-20 21:54 木木子 阅读(1154) 评论(1) 编辑 收藏 举报笔记大概
- CLR属性
- 依赖属性
- 附加属性
CLR属性
public class Human{private int age;public int Age{get{return this.age;}set{if (value >= 0 && value <= 100){this.age = value;}else
{throw new OverflowException("Age overflow");}}}}这就是CLR属性,将private字段包装安全的访问。其实,CLR属性的编译结果是两个方法,仅仅是个语法糖衣。
依赖属性
在WPF中,推出了“依赖属性”这个概念。依赖属性自己没有值,通过Binding从数据源获得值的属性。拥有依赖属性的对象称为“依赖对象”。与CLR属性相比,优势:
- 节省实例对内存的开销。
- 属性值可以通过Binding依赖在其他对象上。
在WPF中,依赖对象的概念被DependencyObject类实现,依赖属性的概念由DependencyProperty类实现。DependencyObject具有GetValue和SetValue两个方法:
public class DependencyObject : DispatcherObject{public object GetValue(DependencyProperty dp){//...
}public void SetValue(DependencyProperty dp, object value){//...
}}DependencyObject是WPF系统中相当底层的一个基类:
如图所示,WPF的所有UI控件都是依赖对象。
最简单的DependencyProperty Coding:
public class Student : DependencyObject{public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name", typeof(string), typeof(Student));}<Window x:Class="Property.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="144" Width="318"><StackPanel><TextBox x:Name="tb1" BorderBrush="Black" Margin="5"/><TextBox x:Name="tb2" BorderBrush="Black" Margin="5"/><Button Content="OK" Margin="5" Click="Button_Click"></Button></StackPanel></Window>private void Button_Click(object sender, RoutedEventArgs e){Student stu = new Student();
stu.SetValue(Student.NameProperty, this.tb1.Text);
this.tb2.Text = (string)stu.GetValue(Student.NameProperty);}下面展示“依赖功能”:
Binding binding = new Binding("Text") { Source = tb1 };BindingOperations.SetBinding(stu, Student.NameProperty, binding);为依赖属性添加一个CLR属性包装:
public class Student : DependencyObject{public string Name{get{return (string)GetValue(NameProperty);}set{SetValue(NameProperty, value);
}}public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name", typeof(string), typeof(Student));}有了CLR属性的包装,我们使用就感觉自然多了。
再把依赖属性升级下,添加SetBinding方法:
public class Student : DependencyObject{public string Name{get{return (string)GetValue(NameProperty);}set{SetValue(NameProperty, value);
}}public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name", typeof(string), typeof(Student));public BindingExpressionBase SetBinding(DependencyProperty dp, BindingBase binding)
{return BindingOperations.SetBinding(this, dp, binding);}}
附加属性
铁锰大哥是这样解释附加属性的:比如一个叫Human的类,可能会与学校有关,也可能与公司有关,那么,设计这样的Human类时,是不是需要把学校、班级、学好、公司、工号等等相关属性加入Human中呢。显然不是很合适,一旦需求改变,这类的实现就需要做改变。
回头去看看布局那笔记,会发现,在Grid中定位,会在某个Control中使用Grid.Column和Grid.Row这些属性,在Canvas中会用到Canvas.Top,DockPanel中是DockPanel.Dock。这些属性就是附加属性,并非定义在Control中。所以,附加属性的作用是,将属性与数据类型(宿主)解耦,让数据类型设计更加灵活。
下面来使用附加属性:
class Human : DependencyObject
{}class School : DependencyObject
{public static int GetGrad(DependencyObject obj){return (int)obj.GetValue(GradProperty);}public static void SetGrad(DependencyObject obj, int value){obj.SetValue(GradProperty, value);
}// Using a DependencyProperty as the backing store for Grad. This enables animation, styling, binding, etc...
public static readonly DependencyProperty GradProperty =DependencyProperty.RegisterAttached("Grad", typeof(int), typeof(School), new UIPropertyMetadata(0));}