如何使用继承DependencyObject的类?

时间:2013-03-14 00:24:48

标签: c# wpf

我从这里开始关注依赖对象的教程:http://tech.pro/tutorial/745/wpf-tutorial-introduction-to-dependency-properties

然而,我仍然有些困惑。我创建了以下类,这纯粹是出于我自己的学习目的而没有实际用途:

namespace DPTest
{
    class Audio : DependencyObject
    {
        public static readonly DependencyProperty fileTypeProperty = DependencyProperty.Register("fileType", typeof(String), typeof(Audio),
        new PropertyMetadata("No File Type", fileTypeChangedCallback, fileTypeCoerceCallback), fileTypeValidationCallback);

        public String fileType
        {
            get
            {
                return (String)GetValue(fileTypeProperty);
            }
            set
            {
                SetValue(fileTypeProperty, value);
            }
        }

        private static void fileTypeChangedCallback(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            Console.WriteLine(e.OldValue + " - " + e.NewValue);
        }

        private static object fileTypeCoerceCallback(DependencyObject obj, object o)
        {
            String s = o as String;
            if (s.Length > 0)
            {
                s = s.Substring(0, 8);
            }

            return s;
        }

        private static bool fileTypeValidationCallback(object value)
        {
            return value != null;
        }
    }
}

几个问题:

  1. 为什么属性是静态的?我不完全理解它是否意味着在对象级别存储值。
  2. Coerce回调做了什么以及为什么包含它?
  3. 我班级的目的是什么?我会在哪里使用它?

2 个答案:

答案 0 :(得分:8)

如果你去Model-View-ViewModel,你很可能不会需要DependencyObject,但是要回答你的具体问题:

  1. DependencyProperty definitions 是静态的,因为DependencyObject的所有实例都共享定义。它们就像fancier per-object property Dictionary。这也允许各种框架功能无缝地工作,例如Binding or rendering updates

  2. 当你需要将属性的变化链接在一起时,
  3. DependencyProperty Coercion occurs。例如,如果您有一个Slider控件,其值应该在最小值和最大值之间,则使用CoerceValue回调来确保它保持在适当的范围内。

  4. DependencyObjects在用户代码中已经失宠,而在很大程度上被WPF开发中的Model-View-ViewModel模式所取代。您仍然会发现DependencyObjects在自定义控件开发中。 DependencyProperties在用户代码中很常见,通常采用Attached Properties的形式。

答案 1 :(得分:3)

依赖项属性本身是静态的,因为您要将属性分配给对象类型。它将属性标识为一个整体,并不仅仅像CLR属性那样捕获值。

正如您在(非静态)CLR属性中看到的那样,存储功能仅由SetValueGetValue处理。您可以将依赖项属性值想象为一个大字典,您只需将一些任意内容放入其中。字典的关键是依赖属性。

强制回调用于强制某种格式的值。在您的情况下,它将确保该字符串只有8个字符长。大多数情况下,您不需要这样的回调。您甚至不需要经常更改属性的属性。最常见的情况是可绑定属性,只需使用标准元数据定义依赖属性即可。

我的课程目的是作为一个例子。如果您没有特定的用例,我建议您甚至不要查看依赖项对象。实际上,您很少将子类型DependencyObject本身。通常,您有一个框架元素或组件,您可以继承并向其添加自定义行为。然后,只要您需要XAML等的可绑定属性,就需要依赖属性。