属性和依赖属性有什么区别?

38

依赖属性的创建方式与属性相同。

依赖属性仅在创建自定义控件时使用吗?

5个回答

64

依赖属性和标准属性有很大的不同。

依赖属性提供的关键特性是支持“绑定”和“动画”。如果您想使用“绑定”或模板绑定为属性分配一个值,那么该属性需要是依赖属性。当对属性进行动画处理时,依赖属性可以跟踪当前分配的值和当前动画值。

另一个常被忽略的优点是仅需要为具有分配值的属性分配存储空间。 典型的控件可以有很多属性,但只有很少的属性实际上被设置了新值,并且大多数属性都保留在其默认值。 使用依赖属性,缺省值会存储为与属性相关的元数据,如果属性保持未分配状态,则不需要每个控件实例分配任何内存。

依赖属性不限于控件(任何派生自DependencyObject的内容都可以拥有它们),但是对于控件或至少FrameworkElements来说,它们最为有用。


12
我认为这个回答值得支持,因为它实际上回答了所提出的问题! - iCollect.it Ltd

23

依赖属性的优点

实际上,相较于普通CLR属性,依赖属性拥有许多优势。

  1. 属性值继承:属性值继承意味着可以在层次结构中覆盖依赖属性的值,以达到最高优先级的值最终被设置的目的。
  2. 数据验证:我们可以自动地触发数据验证,无论何时修改了属性值。
  3. 参与动画:依赖属性可进行动画,WPF动画具有许多能力,可以在一定时间间隔内更改值。定义一个依赖属性,就可以为该属性最终支持动画。
  4. 参与样式:样式是定义控件的元素,可以在依赖属性上使用样式Setters。
  5. 参与模板:模板是定义元素整体结构的元素,通过定义依赖属性,可以在模板中使用它。
  6. DataBinding:由于每个依赖属性本身在修改属性值时会调用INotifyPropertyChanged,因此内部支持DataBinding。要了解更多关于INotifyPropertyChanged的内容,请阅读相关文档。
  7. 回调函数:可以对依赖属性进行回调,以便在属性更改时引发回调。
  8. 资源:依赖属性可以使用资源。因此,在XAML中,您可以为定义依赖属性的资源定义一个资源。
  9. 元数据覆盖:使用PropertyMetaData可以定义某个依赖属性的某些行为。因此,从派生属性覆盖元数据不需要重新定义或重新实现整个属性定义。
  10. 设计支持:依赖属性得到Visual Studio Designer的支持。您可以在设计器的属性窗口中查看控件的所有依赖属性。
在这些中,一些功能只能使用依赖属性来支持。例如,动画样式模板和属性值继承等只能使用依赖属性来实现。如果在这些情况下使用CLR属性,编译器将会生成错误。
请阅读以下文章:
- http://www.codeproject.com/KB/WPF/BeginWPF4.aspx#diff - http://www.dotnetfunda.com/articles/article961-wpf-tutorial--dependency-property-.aspx - http://msdn.microsoft.com/en-us/library/cc221408(VS.95).aspx

很多所谓的“优点”都是有争议的。例如,标准属性可以运行代码来验证被分配的值。归根结底,依赖属性有两个关键作用,支持绑定和允许动画。 - AnthonyWJones

9

依赖属性是一种属性(不是本身,而是依赖于另一个属性,可以是XAML绑定属性),它会注册另一个属性。

依赖属性通过注册来在代码后台注册其他绑定属性。我的项目中使用的一个示例如下:

public static DependencyProperty ImageUri = DependencyProperty.Register("Source", typeof(BitmapImage), typeof(CustomImagePlaceHolder), new PropertyMetadata(null));

在上述代码中,ImageUri是一个依赖属性,它注册了源(Source)。该属性在generic.xaml中被定义/声明(不确定是定义还是声明或者其他什么),如下所示:
..HorizontalAlignment="Center"
VerticalAlignment="Center"
Height="{TemplateBinding Height}"
Width="{TemplateBinding Width}"
/>

这里很重要的一点是,在XAML中模板绑定的值应该在代码后台作为依赖属性进行注册。
因此,当我们在XAML中定义了Image Source应该与Source进行模板绑定时,我们也将同样的Source注册为一个依赖属性。
我们必须说明这个依赖属性的类型,在上面的例子中,Source的类型是BitmapImage,所以我们定义了typeof(BitmapImage)。
现在,这个依赖属性的所有者/父级是我们的CustomImagePlaceHolder自定义控件类,并且我们在注册时再次定义了它。
现在,通过使用以下属性来设置依赖属性的值:
public BitmapImage Source
        {
            get
            {

   string strURI = (string)GetValue(CustomImagePlaceHolder.ImageUri);
                return new BitmapImage(new Uri(strURI));
            }
            set
{
SetValue(CustomImagePlaceHolder.ImageUri, value);
 }

        }

现在,这就是它的工作原理,我们从我们的代码后台或xaml中将值设置到上面定义的源属性中,然后它会设置依赖属性ImageUri的值,进而在模板绑定Source中设置该值,因为我们已经将ImageUri注册为Source,它存在于generic.xaml中。

4
与普通的clr属性相比,依赖属性的主要区别在于依赖属性可以作为绑定的目标。这使您可以将属性的值与其他对象提供的值相结合。
我建议,如果您正在制作自定义控件或标记扩展,通常要将其公共属性公开为依赖属性,以便控件的使用者可以更好地在XAML中操纵设置(而不必在代码后台中执行)。
如果您的属性通常将成为数据绑定的源(例如为TextBlock提供文本),我建议使用标准CLR属性,并使包含类实现INotifyPropertyChanged。
进一步...
依赖属性提供了扩展属性功能的功能,而不是由字段支持的属性。通常,每个此类功能都表示或支持WPF整个功能集的特定功能。
资源
数据绑定
样式
动画
元数据覆盖
属性值继承

http://msdn2.microsoft.com/en-us/library/ms752914.aspx

希望这有所帮助。

1
如果您在VS编辑器中输入propdp并按下tab键,则自动生成的依赖属性文档将被设置为:

//使用DependencyProperty作为MyProperty的后备存储。
这使动画、样式、绑定等成为可能...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接