第7章 深入浅出话属性
7.1 属性(Property)的来龙去脉
程序的本质就是“数据+算法”。
属性仅仅是语法糖衣(Syntax Sugar),一个get方法,一个set方法。
7.2 依赖属性(Dependency Property)
7.2.1 依赖属性对内存的使用方式
WPF允许对象在被创建的时候并不包含用于存储数据的空间(即字段所占用的空间),只保留在需要用到数据时能够获得默认值,借用其他对象数据或实时分配空间的能力——这种对象就称为依赖对象(Dependency Object)而它这种实时获取数据的能力则依靠依赖属性(Dependency Property)来实现。
在WPF系统中,依赖对象的概念被DependencyObject类所实现,依赖属性的概念则由DependencyProperty类实现。
7.2.2 声明和使用依赖属性
想使用自定义的DependencyProperty,宿主一定是DependencyObject的派生类。DependencyProperty实例的声明特点鲜明——引用变量由public static readonly三个修饰符修饰,实例并非使用new操作符得到而是使用DependencyProperty.Register方法生成。
using System.Windows;
using System.Windows.Data;
namespace FirstWpfApplication.Objects
{
class Student : DependencyObject
{
public static readonly DependencyProperty NameProperty =
DependencyProperty.Register("Name", typeof(string), typeof(Student));
public string Name
{
get { return (string)GetValue(NameProperty); }
set { SetValue(NameProperty, value); }
}
public BindingExpressionBase SetBinding(DependencyProperty dp, BindingBase binding)
{
return BindingOperations.SetBinding(this, dp, binding);
}
}
}
<Grid x:Name="g1" Background="Orange" Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<TextBox x:Name="textBox1" Grid.Row="0" Margin="5" BorderBrush="Black"/>
<TextBox x:Name="textBox2" Grid.Row="1" Margin="5" BorderBrush="Black"/>
<Button Content="OK" x:Name="buttonLogin" Grid.Row="4" Width="60" Height="25" Click="buttonLogin_Click"/>
</Grid>
private void buttonLogin_Click(object sender, RoutedEventArgs e)
{
Student stu = new Student();
stu.SetValue(Student.NameProperty, textBox1.Text);
textBox2.Text = (string)stu.GetValue(Student.NameProperty);
}
7.2.3 依赖属性值存取的秘密
一旦程序运行,就会有一个全局的Hastable存在,这个Hastable就是用来注册DependencyProperty实例的地方。
可以用一句话概括DependencyProperty对象的注册于创建:创建一个DependencyProperty实例并用它的CLR属性名和宿主类型名生成hash code,最后把HashCode和DependencyProperty实例作为KeyValue对存入全局的名为PropertyFromName的HashTable中。这样,WPF属性系统通过CLR属性名和宿主类型名就可以从这个全局的HashTable中检索出对应的DependencyProperty实例。最后,生成的DependencyProperty实例被当作返回值交还。