Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 什么';WPF中依赖属性和附加属性之间的区别是什么?_.net_Wpf_Dependency Properties_Attached Properties - Fatal编程技术网

.net 什么';WPF中依赖属性和附加属性之间的区别是什么?

.net 什么';WPF中依赖属性和附加属性之间的区别是什么?,.net,wpf,dependency-properties,attached-properties,.net,Wpf,Dependency Properties,Attached Properties,WPF中的(自定义)依赖属性和附加属性之间有什么区别?每个都有什么用途?实现通常有何不同?附加属性是一种依赖属性。区别在于它们的使用方式 使用附加属性时,该属性是在一个类上定义的,而该类与使用该属性的类不同。这通常用于布局。很好的例子是Panel.ZIndex或Grid.Row-您可以将其应用于控件(即:按钮),但它实际上是在Panel或Grid中定义的。属性“附加”到按钮的实例 例如,这允许容器创建可用于任何UIelement的属性 至于实现上的差异——在定义属性时,基本上只是使用Regist

WPF中的(自定义)依赖属性和附加属性之间有什么区别?每个都有什么用途?实现通常有何不同?

附加属性是一种依赖属性。区别在于它们的使用方式

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

例如,这允许容器创建可用于任何UIelement的属性


至于实现上的差异——在定义属性时,基本上只是使用Register和RegisterAttached的问题。

附加的属性基本上是针对容器元素的。例如,如果您有一个grid和grid.row,现在这被认为是一个grid元素的附加属性。您也可以使用它属性,以设置其在网格中的位置

依赖性属性类似于该属性基本上属于其他类,并在其他类中使用。 就像你有一个长方形
此处高度和宽度是矩形的常规属性,但左侧和顶部是从属属性,因为它属于画布类。

附加属性是一种特殊的从属属性。它们允许您将值附加到对该值一无所知的对象。 这一概念的一个很好的例子是布局面板。每个布局面板需要不同的数据来对齐其子元素。画布需要顶部和左侧,DockPanel需要Dock等。因为您可以编写自己的布局面板,所以列表是无限的。所以你看,不可能在所有WPF控件上都有这些属性。
解决方案是附加的属性。它们由需要来自特定上下文中另一个控件的数据的控件定义。例如,由父布局面板对齐的元素。

我认为可以在类本身中定义附加属性,也可以在另一个类中定义附加属性。我们总是可以使用附加属性来扩展标准的microsoft控件。但是依赖属性,您可以在自己的自定义控件中定义它。e、 可以从标准控件继承控件,并在自己的控件中定义依赖项属性并使用它。这相当于定义附加属性,并在标准控件中使用此附加属性。

Abstract 因为我几乎没有找到关于这个问题的文档,所以我花了一些时间来研究这个问题,但这里有一个答案

将依赖项属性注册为常规属性和附加属性(而不是“哲学”属性)是有区别的(常规属性旨在由声明类型及其派生类型使用,附加属性旨在用作任意
DependencyObject
实例的扩展)。“哲学”,因为正如@MarqueIV在对@ReedCopsey答案的评论中所注意到的,正则属性也可以用于任意
DependencyObject
实例

此外,我不同意其他的回答,即附加属性是“依赖属性类型”,因为这是误导性的——不存在任何依赖属性的“类型”。该框架并不关心该属性是否被注册为附件——甚至无法确定(从某种意义上说,该信息没有被记录,因为它是无关的)。事实上,所有属性都像附加属性一样进行注册,但对于常规属性,会执行一些额外的操作,稍微修改它们的行为

代码摘录 为了省去你自己检查源代码的麻烦,这里有一个简化版本

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

DependencyProperty.Register(
    name: "MyProperty",
    propertyType: typeof(object),
    ownerType: typeof(MyClass))
产生与调用完全相同的结果

DependencyProperty.RegisterAttached(
    name: "MyProperty",
    propertyType: typeof(object),
    ownerType: typeof(MyClass))
但是,在指定元数据时,调用

DependencyProperty.Register(
    name: "MyProperty",
    propertyType: typeof(object),
    ownerType: typeof(MyClass),
    typeMetadata: new FrameworkPropertyMetadata
    {
        CoerceValueCallback = CoerceCallback,
        DefaultValue = "default value",
        PropertyChangedCallback = ChangedCallback
    });
相当于打电话

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
    });
结论 常规依赖项属性和附加依赖项属性之间的关键(也是唯一)区别是通过属性提供的默认元数据。本节甚至提到了这一点:

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

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

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

后果 主要的实际区别是,在常规属性的情况下,
强制值回调
属性更改回调
仅适用于从声明为所有者类型的类型派生的类型,对于附加属性,它们适用于所有类型。例如,在这种情况下:

var d = new DependencyObject();
d.SetValue(SomeClass.SomeProperty, "some value");
登记的
<!-- Implicit property name -->
<ns:SomeClass SomeProperty="some value" /> 

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