实例方法在内存中只有一个拷贝
CLR属性并不会增加内存的负担。属性仅仅是一个语法糖(syntax sugar),对类中字段的封装
依赖属性
-
依赖属性是一种自己没有值,并能通过binding从数据源获取值(依赖在别人身上)的属性。
-
拥有依赖属性的对象被称为依赖对象
-
只有继承DependencyObject的类才可以拥有依赖属性
-
优点
-
节省内存开销
-
属性值可以通过binding依赖在其它对象之上
-
依赖属性的声明
-
注册依赖属性
-
使用public static readonly 三个关键词声明
-
依赖属性名称一般使用Property结尾
-
使用DependencyProperty.Register注册
-
依赖属性包装器
-
严格来讲依赖属性的类型永远都是DependencyProperty。如上例中,string只是依赖属性的注册类型,但通常工作常称为依赖属性的类型
-
public static readonly DependencyProperty MyPropertyProperty
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register("MyProperty", typeof(string), typeof(MainWindow), new PropertyMetadata(string.Empty));
public string MyProperty
{
get { return (string)GetValue(MyPropertyProperty); }
set { SetValue(MyPropertyProperty, value); }
}
依赖属性的机制
-
所有的注册方法都是对私有方法RegisterCommon的调用,原型如下:
private static DependencyProperty RegisterCommon(string name, Type propertyType, Type ownerType, PropertyMetadata defaultMetadata, ValidateValueCallback validateValueCallback)
-
所有的依赖属性都保存在一个hasttable中
private static Hashtable PropertyFromName = new Hashtable();
-
在hashtable中使用name和所属类的类型组合生成的key做为在hashtable中的key(name的hashcode和所属类的类型的hashcode异或)
FromNameKey key = new FromNameKey(name, ownerType);
public FromNameKey(string name, Type ownerType)
{
_name = name;
_ownerType = ownerType;
_hashCode = _name.GetHashCode() ^ _ownerType.GetHashCode();
}
-
在DependencyObject中维护一个依赖属性有效值的数组
private EffectiveValueEntry[] _effectiveValues;
-
在GetValue方法中从这个数组中获取值
entry = _effectiveValues[entryIndex.Index];
-
在SetValue中从添加或更新对应的值
依赖属性读取的优先级
依赖属性的对属性的读取是有优先级的,优先级依次为
-
WPF属性系统强制值
-
由动画过程控制的值
-
本地变量值(存储在_effectiveValues数组中)
-
由上级元素的Template设置的值
-
由隐式样式(Implicit Style)设置的值
-
由样式触发器(Style Trigger)设置的值
-
由模板触发器(Template Trigger)设置的值
-
由样式设置器(Style Setter)设置的值
-
由默认样式(DefaultStyle)设置的值,其实就是由主题(Theme)指定的样式
-
从上级元素继承而来的值
-
默认值(依赖属性的元数据metadata)
附加属性
-
附加属性是依赖对象在某一个特定环境中(如Grid中),由于某种需求被附加的属性(Grid.Row等),
-
附加属性往往定义在依赖对象“从属”的那个对象
-
在使用Binding时和依赖属性没有任何区别
-
声明方式:
-
类型依然是依赖属性
-
包装器和依赖属性有所区别
-
是类的静态方法
-
读取由Get和Set两个方法,而非属性包装器
-
附加属性的使用针对类型而非类的实例,
-
-
注册时也是调用RegisterCommon方法
-
public static string GetMyProperty(DependencyObject obj)
{
return (string)obj.GetValue(MyPropertyProperty);
}
public static void SetMyProperty(DependencyObject obj, string value)
{
obj.SetValue(MyPropertyProperty, value);
}
// Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.RegisterAttached("MyProperty", typeof(string), typeof(MainWindow), new PropertyMetadata(string.Empty));