Как я могу изменить только один параметр метаданных DependencyProperty в подклассе? - PullRequest
5 голосов
/ 04 октября 2011

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

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

Я что-то здесь упускаю?

EDIT

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

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

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

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

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

1 Ответ

2 голосов
/ 04 октября 2011

Копирование метаданных из метаданных базового класса, безусловно, лучший путь. Хотя, к сожалению, класс 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;
}
...