我们可以在不从 DependencyObject 继承的 class 中实现依赖项 属性 吗?如果是,有什么区别?

Can we implement dependency property in a class that does not inherit from DependencyObject? If yes, what is the difference?

我们能否在不继承自 DependencyObject 的 class 中实现依赖项 属性?如果是的话有什么区别?

是的,你可以。这是 Attached 属性 的变体。来自 How to Create an Attached Property:

If your class is defining the attached property strictly for use on other types, then the class does not have to derive from DependencyObject. But you do need to derive from DependencyObject if you follow the overall WPF model of having your attached property also be a dependency property.

不同之处在于您如何定义附加 属性。而不是 Register, you have to use the RegisterAttached 方法,您必须使用以下命名约定将 get 和 set 访问器定义为静态方法,其中 PropertyName 是附加的 属性.

的名称
  • public static object GetPropertyName(object target)
  • public static void SetPropertyName(object target, object value)

让我们看一个简单的例子。假设您要创建一个并排显示图像和文本的按钮。不幸的是,一个 Button 只有一个 Content。由于您现在不想创建自定义控件,因此您尝试通过创建内容模板和附加 属性 作为要显示的图像路径来解决问题。

public static class IconButtonProperties
{
   public static readonly DependencyProperty SourceProperty = DependencyProperty.RegisterAttached(
      "Source", typeof(string), typeof(IconButtonProperties));

   public static void SetSource(UIElement element, string value)
   {
      element.SetValue(SourceProperty, value);
   }

   public static string GetSource(UIElement element)
   {
      return (string) element.GetValue(SourceProperty);
   }
}

现在您可以将此 属性 附加到视图中的按钮以定义图像路径。这里附加的 属性 的不同之处在于您使用其所有者类型 IconButtonProperties.

在不同的类型 (Button) 上定义它
<Button ContentTemplate="{StaticResource ImageTextContentTemplate}"
        local:IconButtonProperties.Source="Resources/MyImage.png"
        Content="Click me!"/>

最后一个重大差异显示在使用附加 属性 和 Binding 的数据模板中。绑定到附加的 属性 时,您必须 put the property in parentheses.

<DataTemplate x:Key="ImageTextContentTemplate">
   <Grid>
      <Grid.ColumnDefinitions>
         <ColumnDefinition Width="Auto"/>
         <ColumnDefinition/>
      </Grid.ColumnDefinitions>
      <Image Grid.Column="0"
             Source="{Binding (local:IconButtonProperties.Source), RelativeSource={RelativeSource AncestorType={x:Type Button}}}"/>
      <TextBlock Grid.Column="1"
                 VerticalAlignment="Center"
                 Margin="5, 0, 0, 0"
                 Text="{Binding}"/>
   </Grid>
</DataTemplate>

如您所见,附加属性对于 WPF 中的可扩展性和绑定来说是无价的。有关一般附加属性的更多信息,您可以参考文档: