如何在某些边界停止WPF属性值继承传播

guz6ccqo  于 2023-04-07  发布在  其他
关注(0)|答案(3)|浏览(207)

我有一个附加的属性,它指定了“inherits”选项来实现WPF属性值继承。我可以看到属性值在整个可视化树中传播。但是,对于大型可视化树,这可能会对性能产生相当大的影响。
因此,我希望我的附加属性的附加属性值继承在某些边界上停止,更具体地说,是特定类的示例。
我读过关于FrameworkElement.InheritanceBehavior的文章,控件可以将其设置为类似SkipAllNext的内容,这会停止属性值继承(尽管对于所有属性),但也会影响资源查找。对资源查找的影响并不理想。
是否有其他方法来控制传播,或者在附加属性中,或者在应该充当边界的类中?
我想达到的目的是:WPF container to turn all child controls to read-only。基于全局开关,通过值继承将窗体中的所有控件变为只读的解决方案非常好。它只是有这里和这里提到的性能损失。

quhf5bfb

quhf5bfb1#

AddOwner似乎可以工作:

class BoundaryElement : FrameworkElement {
    public static readonly DependencyProperty CustomProperty =
        AttachedProperties.CustomProperty.AddOwner(typeof(BoundaryElement),
            new FrameworkPropertyMetadata() {Inherits = false});
}

我尝试通过OverrideMetadata设置Inherits = false,但这只会影响BoundaryElement本身,并且附加的属性值会继续传播到其子节点。

rn0zuynd

rn0zuynd2#

我知道有一种可能性。这不是你真正想要的,但你可以使用DependencyProperty.OverrideMetadata方法来覆盖扩展控件中DependencyPropertyPropertyMetadata

public class SomeControl : OriginalControl
{
    static SomeControl()
    {
        OriginalControl.SomeProperty.OverrideMetadata(typeof(SomeControl), 
            new FrameworkPropertyMetadata(defaultValue, 
            FrameworkPropertyMetadataOptions.OverridesInheritanceBehavior));
    }
}

除此之外,(我可能是错的,但)我不认为你能够实现你的目标……WPF只是没有这样设计。

ecbunoof

ecbunoof3#

对此的解释有点悲伤和复杂,但幸运的是解决方案非常简单。您不需要使用AddOwner(...)
为了在使用DependencyProperty.OverrideMetadata(...)时阻止继承,不能使用FrameworkPropertyMetadata***构造函数***指定FrameworkPropertyMetadataOptions标志“OverridesInheritanceBehavior“。原因是,对于某些FPMO标志,默认的FrameworkPropertyMetadata.Merge(...)函数只处理通过FPM属性设置器显式修改的标志。
Inherits标志/属性是另一个也具有此行为的标志/属性,并且您还需要从任何基本元数据中清除它。因此,使Merge(...)***清除***结果值(在与基本属性元数据合并后)的唯一方法是再次通过其FPM setter显式设置它。
这很令人困惑,不幸的是,这是一个非常不自然/意外/不明显的设计,所以这里有一个例子。假设SomeDependencyPropertybool属性,基本元数据指定falseDefaultValue,并且它启用了DP继承。您希望在派生类MyType上覆盖默认值true
因此,在此页面/问题上讨论的整个问题是以下内容不起作用:

SomeDependencyProperty.OverrideMetadata(typeof(MyType), 
    new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.OverridesInheritanceBehavior));

如上所述,前面有两个问题,但更明显的一个是,即使FPMO.OverridesInheritanceBehavior按预期工作,您也没有***un-set***FPMO.Inherits标志本身。显然,没有办法通过ORing和只能Assert的位标志一起取消位标志。所以本质上,在Merge之后,您将覆盖继承行为--但是继承仍然被启用(由于Merge)。最后,继承仍然最终被启用,您想要的DefaultValue基本上没有效果。
相反,使用属性setter,如下所示,它可以阻止继承,从而允许修改后的DefaultValue生效:

SomeDependencyProperty.OverrideMetadata(typeof(MyType),
    new FrameworkPropertyMetadata(true)
    {
        Inherits = false,
        OverridesInheritanceBehavior = true,
    });

引用:Merge(...)@ FrameworkPropertyMetadata. cs

相关问题