【问题标题】:When to use Dependency Properties何时使用依赖属性
【发布时间】:2010-11-05 07:31:53
【问题描述】:

我有时认为我可能会不必要地使用依赖属性。我什么时候需要使用它?当我有一个依赖于其他属性的属性时?假设我有一个 Color 属性,我希望它依赖于属性 Hue、Saturation、Luminosity 我是否使用依赖属性?或者我用什么?我控制绑定到Color 的控件,以便在更改属性色相、饱和度、亮度时进行更新。

现在我所做的是

public byte Hue {
    get { return _hue; }
    set
    {
        if (_hue == value)
            return;
        _hue = value;
        NotifyPropertyChanged("Hue");
        NotifyPropertyChanged("Color"); // to update controls bound to color
    }
}

但是我认为这不是正确的做事方式吗?如果我有更多影响颜色的属性,我会在所有这些属性中多出 1 行吗?

【问题讨论】:

  • 我不认为这在代码方面是不合理的开销,而且它肯定比添加 DependencyProperty 更轻量级。
  • 如果你要走 hsl-color 路线。我会这样做,所以我不需要经常计算。例如,始终存储 H、S 和 L,仅在需要同步时进行转换。这将极大地提高您的速度。

标签: c# wpf dependency-properties


【解决方案1】:

只有当您希望能够通过 XAML 将 值绑定到某个东西时,您才应该使用 DependencyProperty,例如

<local:MyObject MyDependencyProperty="{Binding ...}" />

更新:正如下面 Ian 所提到的,如果您希望能够为您的属性设置动画或通过样式设置它,则还需要依赖属性

如果您不需要以这种方式工作,那么它是不必要的。例如如果您只想通过 XAML 将值设置为常量(如下所示),则无需使用 DependencyProperty

<local:MyObject MyRegularProperty="Some Value" />

同样,如果您想将 绑定到(例如)您的视图模型上的属性值:

<TextBlock Text="{Binding MyViewModelProperty}" />

那么您不需要使用DependencyProperty。如果您实现了INotifyPropertyChanged,那么Text 在属性更改时仍会更新。

编辑:在重新阅读您的问题时,我不确定您是否使用DependencyProperty 是否会影响您的情况 - 如果我没看错的话,您要做的就是在这些属性中的任何一个发生更改时在 UI 上更新一些属性,对吗?

我认为你目前的实现方式没有任何问题(即在每个 setter 中引发大量 PropertyChanged 事件),但如果你不热衷于那么你可以尝试公开相关子属性以绑定到的单个属性都已计算:

class ColorWrapper
{
    public Color Color  { get; set; }
    public byte Hue
    {
        get { return this.Color.Hue; } //or however this is calculated
}

然后在您的 ViewModel 上有一个 Color 属性,该属性引发 PropertyChanged 事件并通过视图绑定到该事件:

<TextBlock Text="{Binding Color.Hue}" />

正如我所说,我不会说这对你已经拥有的东西有特别的改进。

【讨论】:

  • 绑定不是唯一的用例。如果实现该属性的对象是 UI 元素(有些人在非 UI 对象上实现 DP),则 DP 系统启用各种其他功能,包括动画、样式和(仅限 WPF - Silverlight 没有这些)触发器。此外,如果属性经常保留其默认值,DPs 也很有用,因为每个实例只使用已设置的 DPs 的空间。
  • @Ian Griffiths,关于动画和样式的要点 - 答案已更新。我想你对默认值的评论是有效的,但考虑到在普通属性上实现和使用依赖属性所涉及的开销(特别是如果你还没有处理DependencyObject),我通常不会走那条路。
  • 默认值事物对 WPF 的性能有不小的影响。它为每个对象节省了几百字节,如果你的可视化树包含几千个对象,那就是几百 KB。总内存的一小部分,但足以对有效的 CPU 缓存使用产生巨大影响(尤其是在布局期间)。但是,它可能与任何非 UI 对象无关,并且可能对自定义 UI 元素没有太大帮助,因为您很可能会设置您定义的任何自定义属性。所以我同意...我只是想说明 DP 有多种用途。
  • 有趣 - 我之前没有考虑过性能方面 :)
【解决方案2】:

一般规则是:

  • 对于 XAML 控件,使用依赖属性;

  • 对于数据(您在界面中绑定的数据),请使用INotifyPropertyChanged

有例外,但很少见。

【讨论】:

    【解决方案3】:

    依赖属性的另一个用途是导航日志。元数据中带有 Juornal 标志的页面上的自定义依赖属性包含在 WPF 为页面保存的状态中。

    【讨论】:

      【解决方案4】:

      请记住,尽管依赖属性允许将绑定作为源或目标,但它们也是线程敏感的,并且在序列化时您必须使用代理项,因为 DependencyObject 的序列化是不可序列化的。

      哦,Equals 和 GetHashCode 是密封的 :(

      【讨论】:

        【解决方案5】:

        DP 的另一种用法是附加属性。附加属性是 DependencyProperty 的一种类型,该属性可以在任何其他控件中使用。 例如,您可以在 MyAttachedProperties 类中声明 AttachedProperty,并将其用于 TextBlock、Button、Label...

        附加属性的一些示例:Grid.Row、Grid.Column。定制的:

        public static readonly DependencyProperty DarkThemeProperty =
            DependencyProperty.RegisterAttached("DarkTheme", typeof(Theme), typeof(Page));
         
        public static Theme GetDarkTheme(DependencyObject obj)
        {
            return (Theme)obj.GetValue(DarkThemeProperty);
        }
         
        public static void SetDarkTheme(DependencyObject obj, Theme value)
        {
            obj.SetValue(DarkThemeProperty, value);
        }
        

        【讨论】:

          【解决方案6】:

          我经常踏入 DependencyProperty 的“陷阱”。

          在某个时候,我意识到任何值的每一次更改都会以某种方式和某处触发,可以是算法、流程、用户输入......以及很多事情,但绝不会自行改变.

          获得对触发器的控制,直接从源头挂钩,您永远不需要 DependencyProperty,甚至不需要 INotifyPropertyChanged。我的意思是也许我做错了或做对了,但所有的问题,有时是非常困难的,我只用 RoutedEvents 和 Properties { get , set } -> 在 get, set 你可以做很多事情。在这里无法解决的所有事情,都可以使用 AddHandler 完成,并且在不再需要时不要忘记 RemoveHandler。 在某些情况下,还需要对线程和调度有扎实的了解。 还需要很好地了解如何使用 Lambda 表达式和操作。 (可能不适用于windows phone等应用程序,猜测)

          分别:一个严重的缺点是编码控制和工作量。对于这种方法,我需要编写更多代码并拥有更好的文档,最大的优势是更好地了解您的应用程序中实际发生的事情以及可能发生的事情,扩展是什么。性能没有缺点,它甚至更快,因为当您直接连接到触发器时,您使用的是最轻量和最合适的方法形式 - 仅在必要时执行代码,并且仅在必要时执行代码。

          最后:DependencyProperties 在您实际上不知道可能的关系和反应的响应速度非常快的应用程序中可能有意义。那可能有超过一百万种可能的情况->您不想控制这些情况,您将永远无法完成您的产品。 警告:并非所有看起来都会产生大量未知病例的东西都是未知的。您可以使用 RANGES(从 x 到 y)并编写算法,通过一种方法重新控制数千种可能的情况。

          这是我的两分钱:在大多数情况下不需要 DependencyProperties 和 INotifyPropertyChanged,这只是一种以实际了解您的产品和(有时)性能为代价的更轻松的编码生活的方法。

          (给自己的通知:我写这篇文章是因为我刚遇到一种情况,我认为我需要 DependencyProperty,这一次是真的.. 但没有.. 一个小时的思考,解决方案很容易,找到了触发器。 )

          【讨论】:

            猜你喜欢
            • 2013-05-10
            • 2011-04-02
            • 1970-01-01
            • 2011-07-22
            • 2013-09-17
            • 1970-01-01
            • 2011-07-08
            • 1970-01-01
            • 2011-11-07
            相关资源
            最近更新 更多