如何仅更改子类中 DependencyProperty 元数据的单个选项?

发布于 2024-12-07 18:59:50 字数 836 浏览 2 评论 0原文

我们需要为子类重写DependencyProperty的元数据。现在我知道我可以使用 OverrideMetadata 并指定全新的 FrameworkPropertyMetadata 对象,但在大多数情况下,我希望这个新元数据与现有元数据完全相同,除了设置一个额外的标志(特别是 AffectsMeasure

我的想法是获取现有元数据,创建一个新的元数据对象,将所有成员从旧的手动复制到新的(它不支持Clone) 更改我想要的元数据,然后在 OverrideMetadata 调用中使用新元数据。但是,对于原本如此简单的事情来说,这需要做很多工作!

我在这里错过了什么吗?

编辑

首先,我的意思是 AffectsMeasure 不是 AffectsRender (我在上面进行了更改),

但是......我刚刚发现我们的类已经Width 属性设置了 AffectsMeasure 标志。真正的问题是对于 ListBox 的容器(例如 ListBoxItem),MeasureOverride 在首次初始化时仅被调用一次。

由于这在技术上是一个不相关的问题,因此我将开始一个新问题并关闭这个问题。

以下是新问题的链接:

为什么 ListBoxItem 在宽度更改时不调用 MeasureOverride?

We need to override a DependencyProperty's metadata for our subclass. Now I know that I can use OverrideMetadata and specify entirely new FrameworkPropertyMetadata object, but for the most part I want this new metadata to be exactly the same as the existing metadata except with one additional flag set (specifically AffectsMeasure)

My thought is to get the existing metadata, create a new metadata object, hand-copy all the members over from the old to the new (it doesn't support Clone) changing the one I want, then use the new one in the OverrideMetadata call. But da** that is a lot of work for something otherwise so simple!

Am I missing something here?

EDIT

First things first, I meant AffectsMeasure not AffectsRender (which I've changed above),

BUT... I just found out our class already has the AffectsMeasure flag set for the Width property. The real issue is for containers of a ListBox (e.g. a ListBoxItem) the MeasureOverride is only called once, when first initialized.

Since this is technically an unrelated question, I'll start a new one and close this one.

Here's the link to the new question:

Why is a ListBoxItem not calling MeasureOverride when its width is changed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

嘿看小鸭子会跑 2024-12-14 18:59:50

从基类的元数据复制元数据绝对是正确的方法。尽管不幸的是,FrameworkPropertyMetadata 类没有公开它们给定的标志,但它们被公开为 bool 属性来指示其状态。要以 FrameworkPropertyMetadataOptions 的形式获取这些值,您必须遍历关联的属性并将它们作为一个值读回。

static DerivedClass()
{
    var oldMeta = (FrameworkPropertyMetadata)BaseClass.SomeProperty.GetMetadata(typeof(BaseClass));
    var flags = GetFlags(oldMeta);

    // change the values as needed
    var meta = new FrameworkPropertyMetadata(
        oldMeta.DefaultValue,
        flags,
        oldMeta.PropertyChangedCallback,
        oldMeta.CoerceValueCallback,
        oldMeta.IsAnimationProhibited,
        oldMeta.DefaultUpdateSourceTrigger
    );

    BaseClass.SomeProperty.OverrideMetadata(typeof(DerivedClass), meta);
}

static FrameworkPropertyMetadataOptions GetFlags(FrameworkPropertyMetadata metadata)
{
    FrameworkPropertyMetadataOptions flags = FrameworkPropertyMetadataOptions.None;
    if (metadata.AffectsArrange)
        flags |= FrameworkPropertyMetadataOptions.AffectsArrange;
    if (metadata.AffectsMeasure)
        flags |= FrameworkPropertyMetadataOptions.AffectsMeasure;
    if (metadata.AffectsParentArrange)
        flags |= FrameworkPropertyMetadataOptions.AffectsParentArrange;
    if (metadata.AffectsParentMeasure)
        flags |= FrameworkPropertyMetadataOptions.AffectsParentMeasure;
    if (metadata.AffectsRender)
        flags |= FrameworkPropertyMetadataOptions.AffectsRender;
    if (metadata.BindsTwoWayByDefault)
        flags |= FrameworkPropertyMetadataOptions.BindsTwoWayByDefault;
    if (metadata.Inherits)
        flags |= FrameworkPropertyMetadataOptions.Inherits;
    if (metadata.Journal)
        flags |= FrameworkPropertyMetadataOptions.Journal;
    if (metadata.IsNotDataBindable)
        flags |= FrameworkPropertyMetadataOptions.NotDataBindable;
    if (metadata.OverridesInheritanceBehavior)
        flags |= FrameworkPropertyMetadataOptions.OverridesInheritanceBehavior;
    if (metadata.SubPropertiesDoNotAffectRender)
        flags |= FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender;
    return flags;
}

Copying the metadata from the base class' metadata is definitely the way to go. Though unfortunately the FrameworkPropertyMetadata class doesn't expose the flags as they given, they are exposed as bool properties to indicate their state. To get those values back as a FrameworkPropertyMetadataOptions, you'll have to go through the associated properties and read them back as one.

static DerivedClass()
{
    var oldMeta = (FrameworkPropertyMetadata)BaseClass.SomeProperty.GetMetadata(typeof(BaseClass));
    var flags = GetFlags(oldMeta);

    // change the values as needed
    var meta = new FrameworkPropertyMetadata(
        oldMeta.DefaultValue,
        flags,
        oldMeta.PropertyChangedCallback,
        oldMeta.CoerceValueCallback,
        oldMeta.IsAnimationProhibited,
        oldMeta.DefaultUpdateSourceTrigger
    );

    BaseClass.SomeProperty.OverrideMetadata(typeof(DerivedClass), meta);
}

static FrameworkPropertyMetadataOptions GetFlags(FrameworkPropertyMetadata metadata)
{
    FrameworkPropertyMetadataOptions flags = FrameworkPropertyMetadataOptions.None;
    if (metadata.AffectsArrange)
        flags |= FrameworkPropertyMetadataOptions.AffectsArrange;
    if (metadata.AffectsMeasure)
        flags |= FrameworkPropertyMetadataOptions.AffectsMeasure;
    if (metadata.AffectsParentArrange)
        flags |= FrameworkPropertyMetadataOptions.AffectsParentArrange;
    if (metadata.AffectsParentMeasure)
        flags |= FrameworkPropertyMetadataOptions.AffectsParentMeasure;
    if (metadata.AffectsRender)
        flags |= FrameworkPropertyMetadataOptions.AffectsRender;
    if (metadata.BindsTwoWayByDefault)
        flags |= FrameworkPropertyMetadataOptions.BindsTwoWayByDefault;
    if (metadata.Inherits)
        flags |= FrameworkPropertyMetadataOptions.Inherits;
    if (metadata.Journal)
        flags |= FrameworkPropertyMetadataOptions.Journal;
    if (metadata.IsNotDataBindable)
        flags |= FrameworkPropertyMetadataOptions.NotDataBindable;
    if (metadata.OverridesInheritanceBehavior)
        flags |= FrameworkPropertyMetadataOptions.OverridesInheritanceBehavior;
    if (metadata.SubPropertiesDoNotAffectRender)
        flags |= FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender;
    return flags;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文