How can I change only a single option of a DependencyProperty's metadata in a subclass?
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开发者_Go百科 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?
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;
}
精彩评论