基础知识:
- DependencyObject & DependencyProperty 类位于System.Windows命名空间,程序集:WindowsBase.dll;
- DependencyObject类通过其各子类开启WPF属性系统服务;
- 属性系统的主要功能是:将计算属性值和提供值改变的系统通知;
- DependencyProperty类是另一个在属性系统中起重要作用的类;
- 依赖属性是一种能够注册到WPF属性系统的属性,可通过Styling、Data Binding和Inheritance进行使用;
- DependencyProperty类可将依赖属性注册到属性系统中,并提供每个依赖属性的认证和信息;
- 使用依赖属性的类必须是DependencyObject类的子类,或者说必须是依赖对象才能作为依赖属性的宿主;
- DependencyProperty不能被直接实例化,因为它没有public的构造函数;
- DependencyProperty只能使用静态DependencyProperty.Register()方法创建其实例;
- WPF确保DependencyProperty对象被创建后不能被改变(readonly);
- WPF允许对象在被创建的时候并不创建包含用于存储数据的空间,可只保留在需要用到数据时能够获得默认值,且借用其他对象的数据或实时分配空间的能力来实现。这种对象即依赖对象,这种实时获取数据的能力则由依赖属性实现。
- DependencyProperty必须以DependencyObject为宿主,并借助其SetValue和GetValue方法进行数值的写入与读取;
- 依赖属性必须在静态构造函数中进行设置;
- DependencyObject有 ClearValue 的方法,用于删除属性的本地值;
- 依赖属性的共享,比如,TextBlock.FontFamily属性和Control.FontFamily属性指向同一个静态的依赖项属性TextElement.FOntFamily;使用 DependencyProperty.AddOwner() 方法重用该属性;
- 附加属性也是依赖属性的一种,定义附加属性需要使用 RegisterAttached ()方法;
- ValidateValueCallback回调函数可接受或拒绝新值,用于捕获明显的违反属性约束的错误;而CoerceValueCallback回调函数可将新值改为更能被接受的值,有点类似Validate的效果;
顺序: CoerceValueCallback → ValidateValueCallback → 如果前两个阶段都成功,触发PropertyChangedCallback方法。 ▲ ▲ ▲ ▲
常用类及其一些方法:
◎ DependencyObject类中的SetValue()和GetValue()方法:
//
//
摘要:
//
返回 System.Windows.DependencyObject 的此实例上的依赖项属性的当前有效值。
//
//
参数:
//
dp:
//
要为其检索值的属性的 System.Windows.DependencyProperty 标识符。
//
//
返回结果:
//
返回当前的有效值。
//
//
异常:
//
System.InvalidOperationException:
//
指定的 dp 或其值无效,或者指定的 dp 不存在。
public
object
GetValue(DependencyProperty dp);
//
//
摘要:
//
设置依赖项属性的本地值,该依赖项属性由其标识符指定。
//
//
参数:
//
dp:
//
要设置的依赖项属性的标识符。
//
//
value:
//
新的本地值。
//
//
异常:
//
System.InvalidOperationException:
//
尝试修改只读依赖项属性,或尝试修改密封 System.Windows.DependencyObject 上的属性。
//
//
System.ArgumentException:
//
value 的类型不是为 dp 属性注册时使用的正确类型。
public
void
SetValue(DependencyProperty dp,
object
value);
//
//
摘要:
//
设置只读依赖项属性的本地值,该依赖项属性由其 System.Windows.DependencyPropertyKey 标识符指定。
//
//
参数:
//
key:
//
要设置的属性的 System.Windows.DependencyPropertyKey 标识符。
//
//
value:
//
新的本地值。
public
void
SetValue(DependencyPropertyKey key,
object
value);
◎ DependencyProperty类的Register方法原型:
//
//
摘要:
//
使用指定的属性名称、属性类型和所有者类型注册依赖项属性。
//
//
参数:
//
name:
//
要注册的依赖项对象的名称。 在所有者类型的注册命名空间内,名称必须是唯一的。
//
//
propertyType:
//
属性的类型。
//
//
ownerType:
//
正注册依赖项对象的所有者类型。
//
//
返回结果:
//
一个依赖项对象标识符,应使用它在您的类中设置 public static readonly 字段的值。 然后,在以后使用该标识符引用依赖项对象,用于某些操作,例如以编程方式设置其值,或者获取元数据。
public
static
DependencyProperty Register(
string
name, Type propertyType, Type ownerType);
//
//
摘要:
//
使用指定的属性名称、属性类型、所有者类型和属性元数据注册依赖项属性。
//
//
参数:
//
name:
//
要注册的依赖项对象的名称。
//
//
propertyType:
//
属性的类型。
//
//
ownerType:
//
正注册依赖项对象的所有者类型。
//
//
typeMetadata:
//
依赖项对象的属性元数据。
//
//
返回结果:
//
一个依赖项对象标识符,应使用它在您的类中设置 public static readonly 字段的值。 然后,在以后使用该标识符引用依赖项对象,用于某些操作,例如以编程方式设置其值,或者获取元数据。
public
static
DependencyProperty Register(
string
name, Type propertyType, Type ownerType, PropertyMetadata typeMetadata);
//
//
摘要:
//
使用指定的属性名称、属性类型、所有者类型、属性元数据和属性的值验证回调来注册依赖项属性。
//
//
参数:
//
name:
//
要注册的依赖项对象的名称。
//
//
propertyType:
//
属性的类型。
//
//
ownerType:
//
正注册依赖项对象的所有者类型。
//
//
typeMetadata:
//
依赖项对象的属性元数据。
//
//
validateValueCallback:
//
对回调的引用,除了典型的类型验证之外,该引用还应执行依赖项对象值的任何自定义验证。
//
//
返回结果:
//
一个依赖项对象标识符,应使用它在您的类中设置 public static readonly 字段的值。 然后,在以后使用该标识符引用依赖项对象,用于某些操作,例如以编程方式设置其值,或者获取元数据。
public
static
DependencyProperty Register(
string
name, Type propertyType, Type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback);
◎ ValidateValueCallback的定义:
namespace
System.Windows
{
//
摘要:
//
表示用作回调的方法,用于验证依赖项属性的值是否有效。
//
//
参数:
//
value:
//
要验证的值。
//
//
返回结果:
//
如果该值通过了验证,则为 true;如果提交的值无效,则为 false。
public
delegate
bool
ValidateValueCallback(
object
value);
}
◎ PropertyMetaData类:
//
摘要:
//
定义依赖项对象在应用于特定类型(包括该属性向其注册的条件)时行为的某些方面。
public
PropertyMetadata();
//
//
摘要:
//
使用此元数据将应用于的依赖项对象的指定默认值,初始化 System.Windows.PropertyMetadata 类的新实例。
//
//
参数:
//
defaultValue:
//
要为依赖项对象指定的默认值,通常作为某种特定类型的值提供。
//
//
异常:
//
System.ArgumentException:
//
defaultValue 不能设置为值 System.Windows.DependencyProperty.UnsetValue;请参见“备注”。
public
PropertyMetadata(
object
defaultValue);
//
//
摘要:
//
用指定的 System.Windows.PropertyChangedCallback 实现引用初始化 System.Windows.PropertyMetadata
//
类的新实例。
//
//
参数:
//
propertyChangedCallback:
//
对处理程序实现的引用,每当属性的有效值更改时,属性系统都将调用该处理程序实现。
public
PropertyMetadata(PropertyChangedCallback propertyChangedCallback);
//
//
摘要:
//
用指定的默认值和 System.Windows.PropertyChangedCallback 实现引用初始化 System.Windows.PropertyMetadata
//
类的新实例。
//
//
参数:
//
defaultValue:
//
依赖项对象的默认值,通常作为某种特定类型的值提供。
//
//
propertyChangedCallback:
//
对处理程序实现的引用,每当属性的有效值更改时,属性系统都将调用该处理程序实现。
//
//
异常:
//
System.ArgumentException:
//
defaultValue 不能设置为值 System.Windows.DependencyProperty.UnsetValue;请参见“备注”。
public
PropertyMetadata(
object
defaultValue, PropertyChangedCallback propertyChangedCallback);
//
//
摘要:
//
用指定的默认值和回调初始化 System.Windows.PropertyMetadata 类的新实例。
//
//
参数:
//
defaultValue:
//
依赖项对象的默认值,通常作为某种特定类型的值提供。
//
//
propertyChangedCallback:
//
对处理程序实现的引用,每当属性的有效值更改时,属性系统都将调用该处理程序实现。
//
//
coerceValueCallback:
//
对处理程序实现的引用,每当属性系统对该属性调用 System.Windows.DependencyObject.CoerceValue(System.Windows.DependencyProperty)
//
时都将调用此处理程序实现。
//
//
异常:
//
System.ArgumentException:
//
defaultValue 不能设置为值 System.Windows.DependencyProperty.UnsetValue;请参见“备注”。
public
PropertyMetadata(
object
defaultValue, PropertyChangedCallback propertyChangedCallback, CoerceValueCallback coerceValueCallback);
◎ CoerceValueCallback的定义:
/ /
摘要:
//
为只要重新计算依赖项属性值或专门请求强制转换时就调用的方法提供一个模板。
//
//
参数:
//
d:
//
该属性所在的对象。 在调用该回调时,属性系统将会传递该值。
//
//
baseValue:
//
该属性在尝试执行任何强制转换之前的新值。
//
//
返回结果:
//
强制转换后的值(采用适当的类型)。
public
delegate
object
CoerceValueCallback(DependencyObject d,
object
baseValue);
★对DependencyObject和DependencyProperty的模拟,见源博客链接 http://www.cnblogs.com/eagle1986/archive/2012/08/17/2643332.html :★
public
class
MyDenpendencyObject
{
private
Dictionary<
string
,
object
> properties =
new
Dictionary<
string
,
object
>
();
protected
object
GetValue(MyDenpendencyProperty property)
{
if
(property.OwnerType ==
this
.GetType())
{
return
this
.properties[property.Name];
}
else
{
MyDenpendencyObject parent
=
this
.GetParentElement(property.OwnerType);
return
parent.GetValue(property);
}
}
protected
void
SetValue(MyDenpendencyProperty property,
object
value)
{
this
.properties[property.Name] =
value;
}
private
MyDenpendencyObject GetParentElement(Type type)
{
return
null
;
}
}
public
class
MyDenpendencyProperty
{
private
MyDenpendencyProperty(
string
name, Type valueType, Type ownerType,
object
defaultValue)
{
this
.Name =
Name;
this
.ValueType =
valueType;
this
.OwnerType =
ownerType;
this
.DefaultValue =
defaultValue;
}
public
static
MyDenpendencyProperty Register(
string
name, Type valueType, Type ownerType,
object
defaultValue)
{
return
new
MyDenpendencyProperty(name, valueType, ownerType, defaultValue);
}
public
string
Name
{
get
;
private
set
;
}
public
Type ValueType
{
get
;
private
set
;
}
public
Type OwnerType
{
get
;
private
set
;
}
public
object
DefaultValue
{
get
;
private
set
;
}
}
public
class
MyParentElement : MyDenpendencyObject
{
public
string
Text
{
get
{
return
(
string
)GetValue(TextProperty); }
set
{ SetValue(TextProperty, value); }
}
public
static
readonly
MyDenpendencyProperty TextProperty =
MyDenpendencyProperty.Register(
"
Text
"
,
typeof
(
string
),
typeof
(MyParentElement),
"
This is a super class.
"
);
}
public
class
MyChildElement : MyDenpendencyObject
{
public
string
Text
{
get
{
return
(
string
)GetValue(TextProperty); }
set
{ SetValue(TextProperty, value); }
}
public
static
readonly
MyDenpendencyProperty TextProperty =
MyDenpendencyProperty.Register(
"
Text
"
,
typeof
(
string
),
typeof
(MyParentElement),
"
This is a sub-class.
"
);
}

