Silverlight依赖属性

Silverlight中的依赖属性是一个可以直接从你的后台代码或者从Silverlight的其他一些服务中(如数据绑定, 样式或者是动画)直接设置它的值的属性.这种系统的关键特征是这些不同属性提供者具有不同的优先级。比如一个动画在程序运行时候将会比其他的优先产生效果。这些重叠的因素组成一个非常灵活的系统。他们也给了依赖属性名称-事实上,一个依赖属性依靠多个属性值提供者,每个都有它自己的优先级。
大多数Silverlight元素暴露的属性都是依赖属性。像TextBlock的Text属性,Button的Content属性等等。它暗示了Silverlight依赖属性的一个重要原则--它们被设计成和普通的属性的使用原则一样。这是因为Silverlight类库中的依赖属性通常都是被普通属性定义包裹着。
尽管依赖属性提供了和普通属性同样的可读写特征,但是他们内部的执行方式还是有很大的不同。这种原因主要是因为依赖属性的表现。如果Silverlight的开发者只是简单的在.NET属性系统的基础上添加一些额外的特征,那么他们需要为你的代码提供一个复杂的繁琐的庞大的模块来遍历。如果没有这些额外添加的特征,普通的属性将不支持依赖属性的所有功能。
提示:作为一般的规则,你不需要为了用一个属性,而去知道它是否为依赖属性。但是Silverlight的一些特征对依赖属性还是有限制的,此外你应该了解依赖属性因此你可以在自己的类中定义他们。
定义和注册一个依赖属性
平常你用依赖属性的时间要比定义它的时间多很多.但是仍然有许多原因你要自己定义一个依赖属性。很明显,当你设计一个用户自定义控件的时候它就是一个关键的元素。
定义一个依赖属性并不太困难,只不过语法需要花点时间来适应。它和定义一个普通的.NET属性完全不同。
第一步要定义一个代表你属性的对象。它是DependencyObject类(在System.Windows命名空间)的一个实例。因为你的属性的所有信息要一直有效,因此依赖属性对象在你的类中必须定义为静态变量。
比如,所有Silverlight元素的父元素FrameworkElement定义了一个所有元素共享的Margin的依赖属性。它是这样定义的:
public class FrameworkElement : UIElement{ public static readonly DependencyProperty MarginProperty; ...}
通常,一个定义依赖属性的变量包含一个普通属性的名称,再在这个名称后边加上Property。这样你可以区分依赖属性的定义和实际属性的名称。变量用readonly关键字修饰,意味着它只能在FrameworkElement的静态构造函数中设置。
注意:Silverlight不支持WPF的属性共享机制--换句话说,在一个类中定义了一个属性可以在另一个类中重复使用。但是,依赖属性遵循继承的原则,这意味着一个依赖属性如Margin,定义在FrameworkElement中同样适用于其他的Silverlight元素,因为所有的Silverlight元素都继承自FrameworkElement。
定义一个依赖属性对象只是第一步.为了能让它使用,你需要在你的Silverlight中注册。这一步必须在其他代码适用属性之前完成,所以它必须在相关类的构造函数中实现。
Silverlight保证依赖属性对象不能被直接实例化,因为DependencyProperty没有公开的构造函数。因此一个依赖属性只能被静态方法DependencyProperty.Register()创建。Silverlight同样也保证依赖属性在创建后不能被改变,因为它们都是只读的。然而,他们的值都必须被当做参数来提供给Register()方法。
下边的代码展示了一个依赖属性创建的例子。这里FrameworkElement类用静态的构造函数来初始化MarginProperty:
static FrameworkElement() { MarginProperty = DependencyProperty.Register("Margin", typeof(Thickness), typeof(FrameworkElement), null); }
DependencyProperty.Register()方法主要接受以下的参数
1.属性的名称(在这个列子中式Margin)
2.属性所用的的数据类型(在这个例子中是Thickness结构)
3.属性所属者的类型(在这个例子中是FrameworkElement)
4.一个提供附加信息的PropertyMetadata对象。当前Silverlight用PropertyMetadata存储一些可选择性的信息:一个属性的默认值和当属性值更改时触发的一个回调函数。如果两个都不需要
,就填写一个null,像上边一样。
经过上边的代码,你现在可以注册一个可用的依赖属性。但是,不管典型的属性获取或者设置私有变量的值做法,Silverlight主要是通过定义在基类
DependencyObject中的GetValue()和SetValue().例子
代码public Thickness Margin { get { return (Thickness)GetValue(MarginProperty); } set { SetValue(MarginProperty, value); } }
当你创建一个属性包装器的时候,它里边除了GetValue()和SetValue()方法,不允许出现其他的东西,就想上边的例子一样。你不能添加一些额外的代码来验证数据,触发事件或者其他的
方法。因为Silverlight的其他特征会绕过属性包装器而直接调用GetValue()和SetValue()。一个列子就是当你的Silverlight语法分析器解析你的XAML标记语言并使用它来初始化你的UI界面时候。
你现在完整功能的依赖属性,你可以用属性包装器来设置它像其他.NET属性一样。myElement.Margin=new Thickness(5);
这有一个额外的细节,依赖属性严格遵守优先等级来决定它的当前值。即使你不直接设置依赖属性,它或许已进存在一个值,可能是应用在它的Binding,一个样式或者同元素数继承下来的。
但是,当你直接设置它的值的时候,它会覆盖其他的一些值。
某些时候你可能想移除设置的本地值,让你的属性值像是你从来没有设置过一样。很明显你不能通过设置一个新的值来完成它。但是你可以通过继承另外一个继承与DependencyObject的方法clearValue().例子
myElement.ClearValue(FrameworkElement.MarginProperty)
这个方法告诉Silverlight把这个值看做你从来没有设置它,并把它还原为以前的值。通常会是这个元素的默认值,也可能是通过属性继承或者样式定义得到的。
Tags: 

延伸阅读

最新评论

发表评论