和传统属性的区别在哪里,为什么要搞出这样一个DependencyProperty呢?
- 内存使用量。
我们设计控件,不可避免的要设计很多控件的属性,高度,宽度等等,这样就会有大量(私有)字段的存在,一个继承树下来,低端的对象会无法避免的膨胀。而外部通过GetValue,SetValue暴露属性,内部维护这样一个EffectiveValueEntry的数组,顾名思义,只是维护了一个有效的、设置过值的列表,可以减少内存的使用量。 - 传统属性的局限性。
这个有很多,包括一个属性只能设置一个值,不能得到变化的通知,无法为现有的类添加新的属性等等。
在 MSDN 中,提到当你有下面四种情况时,应该考虑使用DependencyProperty:
- 您希望可在样式中设置此属性。
- 您希望此属性支持数据绑定。
- 您希望此属性支持经过动画处理的值。
- 您希望 Silverlight 属性系统在属性系统本身、环境或用户执行的操作或者读取并使用样式而更改了属性以前的值时进行报告。您的属性可以指定在每次属性系统确定属性值已被明确更改时将调用的回调方法。
一个Silverlight中创建 DependencyProperty 的例子
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Windows.Media.Imaging; namespace SilverlightApplication2 { public partial class SilverlightControl1 : UserControl { /// <summary></summary> /// Declare the dependency property as static, readonly field in your class. /// public static readonly DependencyProperty AquariumGraphicProperty = DependencyProperty.Register( "AquariumGraphic", // Property name typeof(Uri), // Property type typeof(SilverlightControl1), // Type of the dependency property provider new PropertyMetadata(null, // 默认的值 new PropertyChangedCallback(OnUriChanged) // Callback invoked on property value has changes ) ); /// <summary></summary> /// Create the property and use the SetValue/GetValue methods of the DependencyObject class /// public Uri AquariumGraphic { get { return (Uri)GetValue(AquariumGraphicProperty); } set { SetValue(AquariumGraphicProperty, value); } } public SilverlightControl1() { InitializeComponent(); } /// <summary></summary> /// 值变化时,更新显示 /// /// /// private static void OnUriChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { Shape sh = (Shape)d; ImageBrush ib = new ImageBrush(); ib.ImageSource = new BitmapImage(e.NewValue as Uri); sh.Fill = ib; } } }
我们首先来看看 AquariumGraphicProperty ,类型就是DependencyProperty,前面用了static readonly,一个单例模式,有DependencyProperty.Register,看起来像是往容器里注册,其实也差不多。
再来看AquariumGraphic,和传统的属性没什么区别,类型是 Uri 型,有get,set方法。只不过内部的实现分别调用了GetValue和SetValue,这两个方法是DependecyObject(简称DO,是WPF/Silverlight中所有可视Visual的基类)暴露出来的,传入的参数是AquariumGraphicProperty。
需要注意的是运行时,Xaml中是直接调用GetValue和SetValue的。所以,为了让使用XAML设置属性与使用代码设置属性一致,在属性包装器中除了GetValue和SetValue调用以外,不应该包含任何其他逻辑,这是非常重要的。如果需要添加自定义逻辑,应该在Register的回调函数中添加。
参考资料:
.Net3.0里的DependencyProperty(1):引入了DP的一些基本概念
http://www.cnblogs.com/yayx/archive/2007/05/26/761117.html
WPF里的DependencyProperty(2):DP的应用,主要想解释我们为什么要用它
http://www.cnblogs.com/yayx/archive/2008/04/20/1162963.html
WPF里的DependencyProperty(3):主要想演示下怎么用DP
http://www.cnblogs.com/yayx/archive/2008/04/22/1166064.html
WPF/Silverlight为什么要使用Canvas.SetLeft()这样的方法? :附属,从布局应用上解释了下为什么要有AttachedProperty
http://www.cnblogs.com/yayx/archive/2008/04/23/1167110.html
WPF里的DependencyProperty(4):介绍了DP的工作机制
http://www.cnblogs.com/yayx/archive/2008/04/24/1168738.html
WPF里的DependencyProperty(5) :介绍了PropertyMetadata和AttachedProperty
http://www.cnblogs.com/yayx/archive/2008/06/03/1213126.html
Windows Presentation Foundation 体系结构
http://msdn.microsoft.com/en-us/ms750441(zh-cn).aspx
如何学好WPF
http://www.cnblogs.com/zhouyongh/archive/2009/07/31/1536000.html
Tip: How to declare a dependency property in Silverlight?
http://www.silverlightshow.net/tips/Tip-How-to-declare-a-dependancy-property-in-Silverlight.aspx
WPF体系结构-- System.Windows.DependencyObject与智能的控件
http://bbniu.com/forum/thread-478-1-1.html
图解DotNet框架之九:WPF
http://www.cnblogs.com/xugao918/archive/2008/08/01/1258193.html
Silverlight自定义依赖项对象和依赖项属性
http://msdn.microsoft.com/zh-cn/library/cc903933(VS.95).aspx