Как я могу изменить только один параметр метаданных DependencyProperty в подклассе?

Нам нужно переопределить метаданные DependencyProperty для нашего подкласса. Теперь я знаю, что могу использовать OverrideMetadata и указать совершенно новый объект FrameworkPropertyMetadata, но по большей части я хочу, чтобы эти новые метаданные были точно такими же, как существующие метаданные, за исключением одного дополнительного установленного флага (в частности, AffectsMeasure)

Моя идея состоит в том, чтобы получить существующие метаданные, создать новый объект метаданных, вручную скопировать все элементы из старого в новый (он не поддерживает Clone), изменив тот, который я хочу, а затем использовать новый в OverrideMetadata вызов. Но черт возьми, это много работы для чего-то такого простого!

Я что-то упустил здесь?

РЕДАКТИРОВАТЬ

Во-первых, я имел в виду AffectsMeasure, а не AffectsRender (которое я изменил выше),

НО... Я только что узнал, что в нашем классе уже установлен флаг AffectsMeasure для свойства Width. Настоящая проблема заключается в том, что для контейнеров ListBox (например, ListBoxItem) MeasureOverride вызывается только один раз при первой инициализации.

Поскольку это технически не связанный вопрос, я начну новый и закрою этот.

Вот ссылка на новый вопрос:

Почему ListBoxItem не вызывает MeasureOverride при изменении его ширины?


person Mark A. Donohoe    schedule 04.10.2011    source источник
comment
Привет, вы также можете вызвать InvalidateVisual в обработчике событий изменения значения DP, что для меня является более чистым способом сделать это.   -  person    schedule 04.10.2011


Ответы (1)


Копирование метаданных из метаданных базового класса — это, безусловно, правильный путь. Хотя, к сожалению, класс 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;
}
person Jeff Mercado    schedule 04.10.2011
comment
Глядя на реализацию FrameworkPropertyMetadata, он поддерживает другое состояние, поэтому клонирование в целом, вероятно, не будет хорошей идеей. - person Jeff Mercado; 04.10.2011
comment
В любом случае, он не поддерживает «Клон». НО... оказывается, дело не в этом. Я публикую новый вопрос, связанный с тем, с чем мы имеем дело, который представляет собой ListBoxItem, размер которого изменяется, но который не вызывает внутренне MeasureOverride, даже если этот флаг установлен для свойства Width, и мы не знаем Зачем. - person Mark A. Donohoe; 05.10.2011