如何继承DependencyObject类并使DependencyProperties工作?

时间:2014-02-26 21:26:36

标签: wpf

我想创建一组继承DependencyObject类的控件。 (对于这个故事,我不想在这些控件中进行测量/排列操作,但这不是重点。)

我天真地认为DependenciesProperties会直接处理这些控件。事实并非如此。

第一个问题

从概念上讲,由于我不更新DependencyObject的父级,显然DependencyProperties无法从父级中找到它们的值,因此不会继承DataContext等属性。

我找到了一半的解决方案:

using System;
using System.Reflection;
using System.Windows;

namespace ControlsLibrary.Base
{
    public class FrameworkElement : DependencyObject
    {
        private static MethodInfo _setInheritanceParentMethod;

        static FrameworkElement()
        {
            // NOTE: Hack to expose a hidden method.
            _setInheritanceParentMethod = typeof(DependencyObject).GetMethod("SetInheritanceParent", BindingFlags.Instance | BindingFlags.NonPublic);
        }

        private delegate void SetInheritanceParentDelegate(DependencyObject obj);

        private readonly SetInheritanceParentDelegate _setInheritanceParent;

        private DependencyObject _inheritanceParent = null;

        public FrameworkElement()
        {
            // NOTE: Prefer the use of delegates rather than MethodInfo.Invoke.
            _setInheritanceParent = (SetInheritanceParentDelegate)Delegate.CreateDelegate(typeof(SetInheritanceParentDelegate), this, _setInheritanceParentMethod);
        }

        public DependencyObject InheritanceParent
        {
            get { return _inheritanceParent; }
            set
            {
                if (_inheritanceParent != value)
                {
                    _inheritanceParent = value;

                    _setInheritanceParent(_inheritanceParent);
                }
            }
        }

        public object DataContext
        {
            get { return (object)GetValue(DataContextProperty); }
            set { SetValue(DataContextProperty, value); }
        }

        // Using a DependencyProperty as the backing store for DataContext.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DataContextProperty =
            System.Windows.FrameworkElement.DataContextProperty.AddOwner(typeof(FrameworkElement), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits));
    }
}

使用该解决方案,我能够继承两个FrameworkElements之间的DataContext

var parent = new FrameworkElement();
var child = new FrameworkElement();

Assert.AreEqual(null, parent.DataContext);
Assert.AreEqual(null, child.DataContext);

parent.DataContext = "Test";
Assert.AreEqual("Test", parent.DataContext);
Assert.AreEqual(null, child.DataContext);

child.InheritanceParent = parent;
Assert.AreEqual("Test", parent.DataContext);
Assert.AreEqual("Test", child.DataContext);

parent.DataContext = "Check";
Assert.AreEqual("Check", parent.DataContext);
Assert.AreEqual("Check", child.DataContext);

child.DataContext = "Test";
Assert.AreEqual("Check", parent.DataContext);
Assert.AreEqual("Test", child.DataContext);

child.InheritanceParent = null;
Assert.AreEqual("Check", parent.DataContext);
Assert.AreEqual("Test", child.DataContext);

以及Wpf.FrameworkElement与我的一个FrameworkElement之间。

var parent = new System.Windows.FrameworkElement();
var child = new ControlsLibrary.Base.FrameworkElement();

大!

第二个问题

我尝试了三个FrameworkElements并且它不起作用...... DataContext继承了两个对象,但没有三个对象......

var element0 = new FrameworkElement();
var element1 = new FrameworkElement();
var element2 = new FrameworkElement();

element1.InheritanceParent = element0;
element2.InheritanceParent = element1;
Assert.AreEqual("Test", element0.DataContext);
Assert.AreEqual("Test", element1.DataContext); // --> This one works.
Assert.AreEqual("Test", element2.DataContext); // --> But this one is null!!!

所以我猜我做错了。

问题

所以问题是:如何继承DependencyObject类并使DependencyProperties工作?

换句话说:有人已经“入侵”了DependencyObject类吗?有人可以提供一个完整的解释,说明我必须做些什么才能拥有一个功能齐全的FrameworkElement?

还是死了?

如果有必要,我可以帮助其他人了解它是如何运作的!

谢谢!

0 个答案:

没有答案