0

我们有两个外部定义的、逻辑上独占(业务方面)的附加属性,它们都是可继承的。取决于哪个设置最接近我们正在阅读的 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) 。这就是为什么我需要知道源在哪里/离我正在检查的元素有多远。

4

3 回答 3

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
于 2012-06-01T09:21:13.680 回答
0

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

您消除了反映整个可视化树的需要,并依赖于依赖属性的内置机制。

于 2012-06-18T14:36:31.173 回答
0

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

当然,这本身并不能告诉你足够的信息,但从那里开始很容易。

有了这些知识,您只需编写一个方法,该方法接受相关对象并检查两个属性是否存在(请记住,它们可能由于默认值、样式、模板或其他原因而被“设置”)并相应地继续:

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

  • 如果它们都已设置,则使用单个属性使用的相同优先级。(即Localbeats InheritInheritbeatsDefault等)您只是在同一级别将两个属性源的值相互比较。

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

  • 如果它们相同并且它 Inherit,则沿着逻辑树(或可视化,具体取决于您的需要)并递归调用传入父级的相同函数。

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

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

于 2012-06-01T18:16:16.740 回答