我们有两个外部定义的,逻辑上独占的(业务方面)附加属性,这两个属性都是可继承的。根据最接近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)。这就是为什么我需要知道源的位置/距我正在检查的元素的距离。
答案 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
节拍Inherit
,Inherit
节拍Default
等等。)您只是在同一级别比较两个属性来源的值。
如果它们的来源相同且不是Inherit
,则使用在您的业务逻辑中优先的那个(在我们的例子中为AProp2。)
如果它们是相同的并且是 Inherit
,那么你走上逻辑树(或视觉上取决于你的需要)并递归调用传入的相同函数父节点。
当然,如果这个属性受到动画和其他类似的影响,那么逻辑变得有点复杂,但在我们的例子中,它要么在本地设置,要么继承。其他并不多。
现在很简单,我正在看它。希望这有助于其他人!
答案 2 :(得分:0)
使用元组包含两个值。最接近的继承属性将包含一个值或另一个值,它将优先。
您无需反映整个可视树,并依赖内置的依赖属性机制。