Loading [MathJax]/jax/input/TeX/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >在WPF中,依赖属性和附加属性有什么不同?

在WPF中,依赖属性和附加属性有什么不同?
EN

Stack Overflow用户
提问于 2009-08-06 10:52:12
回答 5查看 36.7K关注 0票数 94

在WPF中,(自定义)依赖属性和附加属性有什么不同?每一个都有什么用处?这些实现通常有什么不同?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2018-05-09 16:07:16

摘要

因为我几乎没有找到关于这个问题的文档,所以我在source code上花了一些时间,但这是一个答案。

将依赖属性注册为常规属性和附加属性之间存在差异,而不是“哲学”属性(常规属性用于声明类型及其派生类型,附加属性用于任意DependencyObject实例的扩展)。“哲学”,因为,正如@MarqueIV在他对@ReedCopsey的回答的评论中注意到的那样,常规属性也可以用于任意的DependencyObject实例。

此外,我不得不不同意其他关于附加属性是“依赖属性的类型”的回答,因为它具有误导性--没有任何依赖属性的“类型”。框架并不关心属性是否被注册为附加的--它甚至不可能确定(从这个意义上说,这个信息没有被记录,因为它是不相关的)。实际上,所有属性都被注册为附加属性,但对于常规属性,需要做一些额外的操作来稍微修改它们的行为。

代码摘录

为了省去您自己翻阅源代码的麻烦,下面是所发生的事情的精简版本。

注册未指定元数据的属性时,调用

代码语言:javascript
运行
AI代码解释
复制
DependencyProperty.Register(
    name: "MyProperty",
    propertyType: typeof(object),
    ownerType: typeof(MyClass))

产生与调用完全相同的结果

代码语言:javascript
运行
AI代码解释
复制
DependencyProperty.RegisterAttached(
    name: "MyProperty",
    propertyType: typeof(object),
    ownerType: typeof(MyClass))

但是,在指定元数据时,调用

代码语言:javascript
运行
AI代码解释
复制
DependencyProperty.Register(
    name: "MyProperty",
    propertyType: typeof(object),
    ownerType: typeof(MyClass),
    typeMetadata: new FrameworkPropertyMetadata
    {
        CoerceValueCallback = CoerceCallback,
        DefaultValue = "default value",
        PropertyChangedCallback = ChangedCallback
    });

等同于调用

代码语言:javascript
运行
AI代码解释
复制
var property = DependencyProperty.RegisterAttached(
    name: "MyProperty",
    propertyType: typeof(object),
    ownerType: typeof(MyClass),
    defaultMetadata: new PropertyMetadata
    {
        DefaultValue = "default value",
    });
property.OverrideMetadata(
    forType: typeof(MyClass),
    typeMetadata: new FrameworkPropertyMetadata
    {
        CoerceValueCallback = CoerceCallback,
        DefaultValue = "default value",
        PropertyChangedCallback = ChangedCallback
    });

结论

常规依赖项属性和附加依赖项属性之间的关键(也是唯一的)区别是通过DependencyProperty.DefaultMetadata属性提供的默认元数据。这甚至在一节中也提到过:

对于非附加属性,不能将此属性返回的元数据类型强制转换为PropertyMetadata类型的派生类型,即使该属性最初注册为派生元数据类型也是如此。如果您希望原始注册的元数据包括其原始的可能派生的元数据类型,请改为调用GetMetadata(Type),并将原始注册类型作为参数传递。

对于附加属性,此属性返回的元数据的类型将与原始RegisterAttached注册方法中给定的类型相匹配。

这在所提供的代码中是清晰可见的。注册方法中也隐藏了一些小提示,例如,对于RegisterAttached,元数据参数被命名为defaultMetadata,而对于Register,它被命名为typeMetadata。对于附加属性,提供的元数据将成为默认元数据。但是,对于常规属性,默认元数据始终是仅设置了DefaultValuePropertyMetadata的新实例(来自提供的元数据或自动设置)。只有对OverrideMetadata的后续调用才实际使用所提供的元数据。

后果

主要的实际区别在于,在常规属性的情况下,CoerceValueCallbackPropertyChangedCallback仅适用于从声明为所有者类型的类型派生的类型,而对于附加属性,它们适用于所有类型。例如,在此场景中:

代码语言:javascript
运行
AI代码解释
复制
var d = new DependencyObject();
d.SetValue(SomeClass.SomeProperty, "some value");

如果属性被注册为附加属性,则注册的PropertyChangedCallback 将被称为,但如果它被注册为常规属性,则将不被称为CoerceValueCallback也是如此。

第二个不同之处在于OverrideMetadata要求所提供的类型派生自DependencyObject。实际上,这意味着常规属性的所有者类型必须从DependencyObject派生,而中的附加属性可以是任何类型(包括静态类、结构、枚举、委托等)。

补充

除了@MarqueIV的建议之外,我还在几个场合遇到过这样的观点,即常规属性和附加属性在XAML中的使用方式不同。也就是说,常规属性需要隐式名称语法,而不是附加属性所需的显式名称语法。从技术上讲,这不是真的,尽管在实践中通常是这样的。为了清楚起见:

代码语言:javascript
运行
AI代码解释
复制
<!-- Implicit property name -->
<ns:SomeClass SomeProperty="some value" /> 

<!-- Explicit property name -->
<DependencyObject ns:SomeClass.SomeProperty="some value" />

在纯XAML中,控制这些语法使用的唯一规则如下:

  • 隐式名称语法可用于元素当且仅当此元素表示的类具有该代码名称语法的CLR属性时才可用于元素当且仅当全名的第一部分指定的类公开了适当的静态get/set方法(称为访问器),其名称与全名的第二部分匹配<

>F257

满足这些条件使您可以使用相应的语法,而不管支持依赖项属性是注册为常规还是附加。

现在所提到的误解是由于绝大多数教程(连同现有的Visual Studio代码片段)指导您对常规依赖属性使用CLR属性,并为附加的属性获取/设置访问器。但是,没有什么可以阻止您同时使用这两种语法,允许您使用您喜欢的任何语法。

票数 25
EN

Stack Overflow用户

发布于 2009-08-06 10:56:17

附加属性是一种依赖属性。不同之处在于如何使用它们。

通过附加属性,该属性被定义在与使用它的类不同的类上。这通常用于布局。很好的例子是Panel.ZIndex或Grid.Row -你将其应用于一个控件(即:按钮),但它实际上是在面板或网格中定义的。该属性被“附加”到按钮的实例上。

例如,这允许容器创建可在任何UIelement上使用的属性。

至于实现的区别--这基本上就是在定义属性时使用注册和RegisterAttached的问题。

票数 71
EN

Stack Overflow用户

发布于 2012-01-10 11:33:57

附加属性基本上是指容器elements.like如果你有一个网格,你现在有一个grid.row这被认为是一个网格element.also的附加属性你可以在文本框,按钮等中使用这个属性来设置它在网格中的位置。

依赖属性类似于属性基本上属于某个其他类,并在其他类中使用。就像你在这里有一个矩形一样,height和width是rectangle的常规属性,但是left和top是依赖属性,因为它属于Canvass类。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1240699

复制
相关文章
WPF依赖属性(wpf 依赖属性)
依赖属性就是一种自己可以没有值,并且可以通过绑定从其他数据源获取值。依赖属性可支持WPF中的样式设置、数据绑定、继承、动画及默认值。
全栈程序员站长
2022/07/28
2.2K0
WPF依赖属性(wpf 依赖属性)
[UWP]为附加属性和依赖属性自定义代码段(兼容UWP和WPF)
之前介绍过依赖属性和附加属性的代码段,这两个代码段我用了很多年,一直都帮了我很多。不过这两个代码段我也多年没修改过,Resharper老是提示我生成的代码可以修改,它这么有诚意,这次就只好从了它,顺便简单介绍下怎么自定义代码段。
dino.c
2019/01/18
7540
[UWP]为附加属性和依赖属性自定义代码段(兼容UWP和WPF)
UWP基础教程 - XAML依赖属性和附加属性
前面两章介绍了XAML的命名空间、元素和属性的概念,从本篇开始接下来会介绍XAML的高级特性,本篇主要会介绍两个概念: 依赖属性(Dependency Properties) 附加属性(Attached Properties) 依赖属性 英文称为Dependency Properties,是XAML特有的属性系统。在传统.Net应用开发中,CLR属性是面向对象编程的基础,主要提供对私有字段的访问封装,开发人员可以使用get和set访问器实现读写属性操作。在UWP应用开发中,依赖属性和CLR属性类似,同样提供
陈仁松
2018/03/20
1.2K0
UWP基础教程 - XAML依赖属性和附加属性
附加属性
附加属性我们早就使用过,常见的用于控件定位的Grid.Row,Grid.Column就是附加属性,那这个东西具体是什么意思呢?请设想这样的情景:一个学生,他在社团可以是社长,他在班内可以是班长,在赛场又可以是运动员,这些特定的属性,并不是每个学生都具有的,只有学生参与了或者在某个环境中,才具有这样的属性。那我们在定义学生类时,就不能把这些属性定义进去,为了解决这种在某些环境中才具有特定属性的情况,WPF引入了附加属性,附加属性就是一个对象可以被它外部的环境附加某些属性,而对象本身实际上不具有这样的属性。
宿春磊Charles
2021/11/05
8340
在 WPF 中获取一个依赖对象的所有依赖项属性
本来 .NET 中提供了一些专供设计器使用的类型 TypeDescriptor 可以帮助设计器找到一个类型或者组件的所有可以设置的属性,不过我们也可以通过此方法来获取所有可供使用的属性。
walterlv
2023/10/22
5500
学习WPF——初识依赖项属性
入门 首先创建一个依赖项属性 然后绑定父容器的DataContext到这个依赖项的实例 接着绑定子元素的属性到依赖项属性(注意Button的Content属性) 程序最终的运行结果: 说明 首先是定义
liulun
2018/01/12
9510
学习WPF——初识依赖项属性
WPF 调试依赖属性变更方法
在 WPF 里面,所有的依赖属性都有带通知的功能,通过带通知的功能,可以在通知里加上断点,通过调用堆栈了解是哪个模块调用的
林德熙
2022/08/12
4110
[UWP]依赖属性2:使用依赖属性
以上代码为一个相对完成的依赖属性例子(还有一些功能比较少用就不写出了),从这段代码可以看出,自定义依赖属性的步骤如下:
dino.c
2019/01/18
1.4K0
[翻译] WPF 中用户控件 DataContext/Binding 和依赖属性的问题
ProgrammingDude(asked Dec 8, 2015 at 21:24)
独立观察员
2022/12/06
9990
C# 附加属性
附加属性我们早就使用过,常见的用于控件定位的Grid.Row,Grid.Column就是附加属性,那这个东西具体是什么意思呢?请设想这样的情景:一个学生,他在社团可以是社长,他在班内可以是班长,在赛场又可以是运动员,这些特定的属性,并不是每个学生都具有的,只有学生参与了或者在某个环境中,才具有这样的属性。那我们在定义学生类时,就不能把这些属性定义进去,为了解决这种在某些环境中才具有特定属性的情况,WPF引入了附加属性,附加属性就是一个对象可以被它外部的环境附加某些属性,而对象本身实际上不具有这样的属性。
zls365
2021/09/02
1.2K0
C# 附加属性
[UWP]附加属性1:概述
附加属性依赖属性的一种特殊形式,常见的Grid.Row,Canvas.Left都是附加属性。
dino.c
2019/01/18
7410
WPF依赖属性的正确学习方法
我在学习WPF的早期,对依赖属性理解一直都非常的不到位,其恶果就是,我每次在写依赖属性的时候,需要翻过去的代码来复制黏贴。
Kiba518
2019/07/25
2K0
WPF依赖属性的正确学习方法
WPF 依赖属性绑定不上调试方法
在写 WPF 程序的时候会遇到依赖属性绑定了,但是值没有更新或者没有绑定上的问题,本文告诉大家可以如何调试
林德熙
2020/07/06
1.7K0
WPF 附加属性提供某个元素拥有拖拽窗口的功能
我需要窗口内的某个元素拥有拖动整个窗口的功能,也就是这个元素在拖动的时候是拖动整个窗口。而且我还开出一个有趣的方法,这个作为窗口的拖拽的元素如果是用户在元素上拖动,那么将会拖动窗口,如果用户是点击,将会触发点击事件
林德熙
2020/07/07
8140
2018-10-28-WPF的只读依赖属性
依赖属性的概念大家应该都很清楚,那么什么是只读依赖属性呢? ---- 为何要用只读依赖属性 当某些时候,你的依赖属性只是为了表征一种多因素影响的复合状态。这种状态不适合由外部显示设置。比如常见的IsMouseOver,当且仅当这个属性由鼠标输入设备进行内部赋值时,结果才是有效的。而在于外部进行赋值时,其值和相应的真实设备状态是不一致的。 只读依赖属性的局限 由于不可设置,只读依赖属性会被限制众多解决方案,如数据绑定,验证,动画,继承等等。 只读依赖属性的用法 由于仍可以在属性发生改变时引发通知,只读依赖属
黄腾霄
2020/06/10
6140
WPF中Image的Stretch属性
有时候我们在WPF程序中设置了图片的Width和Height,但图片显示出来的宽和高并不是我们预期的效果,这实际上是由于Image的默认Stretch属性导致的
zls365
2020/12/15
2.1K0
WPF 让普通 CLR 属性支持 XAML 绑定(非依赖属性),这样 MarkupExtension 中定义的属性也能使用绑定了
如果你写了一个 MarkupExtension 在 XAML 当中使用,你会发现你在 MarkupExtension 中定时的属性是无法使用 XAML 绑定的,因为 MarkupExtension 不是一个 DependencyObject。
walterlv
2020/02/10
1.7K0
剖析依赖属性
这节来讲一下WPF中的依赖属性 (Dependency Property)。
宿春磊Charles
2021/11/05
4730
Qml好用的default附加属性
  看似很没用的属性却说有用,还说好用。第一个例子看起来和常规做法差不多。那么我们看看第二个例子使用起来是如何好用的。   Group.qml组件:
Qt君
2019/07/15
1.6K0
Qml好用的default附加属性
【说站】css中sticky属性有什么特点
也就是说,如果你设置了top:50px,当sticky元素到达相对定位元素顶部50px的位置时,固定,不再向上移动。
很酷的站长
2022/11/23
3050
【说站】css中sticky属性有什么特点

相似问题

在WPF中,x:Name和Name属性有什么不同?

1471

限制wpf中的附加依赖项属性

11

ValidationRule WPF的附加或依赖属性

11

WPF如何将附加属性绑定到依赖属性

112

Wpf样式和附加属性

10
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文