你能确定一个可继承的附属物的来源吗?

时间:2012-05-29 21:09:22

标签: wpf inheritance dependency-properties attached-properties

我们有两个外部定义的,逻辑上独占的(业务方面)附加属性,这两个属性都是可继承的。根据最接近DependencyObject设置的内容,我们正在读取它们,这决定了我们在逻辑中使用的内容,如下所示。

注意:我不想知道 继承了你可以通过DependencyPropertyHelper.GetValueSource做什么,我想从哪里知道,所以我可以确定优先顺序。

考虑以下可视树层次结构和附加属性:

Root // <-- AProp1 first set here
    Child
        GrandChild // <-- AProp2 first set here
            GreatGrandChild // <-- AProp1 re-applied here
                GreatGreatGrandChild
  • 在Root的情况下,AProp1是单独设置的,因此我们使用AProp1。

  • 对于Child,AProp1是继承的,因此我们仍然使用AProp1。

  • 在GrandChild的情况下,设置了AProp2,但是由于继承,AProp1也有一个值。但是,由于AProp2直接设置在此对象上(即距离'0'水平距离)与AProp1(距离'2'),AProp2优先于我们的业务逻辑。

  • 在GreatGrandChild的情况下,再次设置AProp1(距离'0'之外),优先于AProp2(距离'1')

  • 最后,在GreatGreatGrandChild的情况下,同样,AProp1和AProp2都是通过继承获取的,但是因为AProp1在层次结构中设置得更近(距离'1'远)而不是AProp2(距离'2 '离开',AProp1是我们想要使用的。

如果我能找到源头,我知道我可以简单地走链子并计算距离。我只需要来源。

注意:

对于记录,是的,它们都可以设置在同一级别,在这种情况下,AProp2优先,但这与此问题无关。

即使使用相同的值作为提升其优先级的方法,也可以重新应用属性(请参阅GreatGrandChild)。这就是为什么我需要知道源的位置/距我正在检查的元素的距离。

3 个答案:

答案 0 :(得分:1)

一个非常有趣的问题!您可以将附加属性添加到存储类型的DependencyObject(如果类型对您不利,则可以存储对象引用),我们将使用它来记录属性设置的对象类型。

 public class DependencyPropertyExtension
    {
        public static Type GetAprop1Owner(DependencyObject obj)
        {
            return (Type)obj.GetValue(Aprop1OwnerProperty);
        }

        public static void SetAprop1Owner(DependencyObject obj, Type value)
        {
            obj.SetValue(Aprop1OwnerProperty, value);
        }

        public static readonly DependencyProperty Aprop1OwnerProperty = DependencyProperty.RegisterAttached("Aprop1Owner", typeof(Type), typeof(DependencyProperty), new UIPropertyMetadata(null));
    }

然后在依赖属性Aprop1中添加一些UIPropertyMetaData,以便我们可以响应更新。

public object Aprop1
{
    get { return (object)GetValue(Aprop1Property); }
    set { SetValue(Aprop1Property, value); }
}
public static readonly DependencyProperty Aprop1Property =
    DependencyProperty.Register("Aprop1", typeof(object), typeof(Level1), new UIPropertyMetadata(null, new PropertyChangedCallback( (s, e) =>
        {
            DependencyPropertyExtension.SetAprop1Owner(s, s.GetType());
        })));

我在这里所做的就是将附加属性更新为正在设置属性的对象的类型。

您可以使用

从任何对象中读取此信息
DependencyPropertyExtension.GetAprop1Owner(testObject).FullName

答案 1 :(得分:0)

我想我已经找到了。其中一个'一直在你面前'的事情。它围绕使用DependencyPropertyHelper.GetValueSource来确定对象的属性值是否被继承。

当然,这本身并不足以告诉你,但从那里开始很容易。

有了这些知识,你只需编写一个方法来接收有问题的对象并检查两个属性是否存在(记住,由于默认值,样式,模板或其他原因,它们可能是'set')并继续相应地:

  • 如果只设置了其中一个,那就是你使用的那个,你已经完成了。根据需要处理。

  • 如果它们都已设置,请使用与单个属性相同的优先级。 (即Local节拍InheritInherit节拍Default等等。)您只是在同一级别比较两个属性来源的值。

  • 如果它们的来源相同且不是Inherit,则使用在您的业务逻辑中优先的那个(在我们的例子中为AProp2。)

  • 如果它们是相同的并且 Inherit,那么你走上逻辑树(或视觉上取决于你的需要)并递归调用传入的相同函数父节点。

当然,如果这个属性受到动画和其他类似的影响,那么逻辑变得有点复杂,但在我们的例子中,它要么在本地设置,要么继承。其他并不多。

现在很简单,我正在看它。希望这有助于其他人!

答案 2 :(得分:0)

使用元组包含两个值。最接近的继承属性将包含一个值或另一个值,它将优先。

您无需反映整个可视树,并依赖内置的依赖属性机制。