我了解这些类之间的基本区别,PropertyMetadata用于备份属性,UIPropertyMetadata用于支持动画,FrameworkMetadata用于在用户控件中使用框架属性。
但我只理解理论部分。如果您能提供一个最简单的示例,使用这3个不同依赖属性的类,明确区分它们,那将是非常有帮助的。
谢谢提前。
但我只理解理论部分。如果您能提供一个最简单的示例,使用这3个不同依赖属性的类,明确区分它们,那将是非常有帮助的。
谢谢提前。
来源:PropertyMetadata与FrameworkPropertyMetadata
当你实现自定义依赖属性并通过调用
DependencyProperty.Register
注册该属性时,你需要传递一个PropertyMetadata
的实例来指定一些属性元数据。这可以是PropertyMetadata
类的实例或其子类的实例。具体区别如下:
PropertyMetadata
– 基本的依赖属性相关元数据
CoerceValueCallback
– 在设置值时强制执行的回调函数DefaultValue
– 属性的默认值PropertyChangedCallback
– 对属性的新有效值做出响应的回调函数
UIPropertyMetadata
– 派生自PropertyMetadata
并添加了以下内容:
IsAnimationProhibited
– 禁用此属性的动画效果?
FrameworkPropertyMetadata
– 派生自UIPropertyMetadata
并添加了以下内容:
AffectsArrange
、AffectsMeasure
、AffectsParentArrange
、AffectsParentMeasure
、AffectsRender
– 在属性值更改后是否重新运行布局计算?BindsTwoWayByDefault
、DefaultUpdateSourceTrigger
、IsDataBindingAllowed
、IsNotDataBindable
– 指定属性在数据绑定中的参与方式Inherits
,OverridesInheritanceBehavior
- 这个属性是否支持继承?Journal
- 在记录日志时是否存储此值?SubPropertiesDoNotAffectRender
- 当布局更改时,是否检查此对象的属性?
PropertyMetadata和FrameworkPropertyMetadata之间的一个重要实际区别是,后者允许指定一组FrameworkPropertyMetadataOptions。
例如,指定FrameworkPropertyMetadataOptions.AffectsRender
将关心在属性更改时启动UIElement的重新渲染。如果没有此标志,则必须在PropertyChangedCallback中手动执行此操作。
FrameworkPropertyMetadata
和UIPropertyMetadata
暴露的所有行为都由标志位控制,这些标志位记录在单个enum
(32位uint
)字段_flags
中,该字段声明在PropertyMetadata
基类中,尽管其中没有任何标志位被公开。以下是该enum
的声明:
内部枚举 MetadataFlags : uint { DefaultValueModifiedID /**/= 0b_00000000_00000000_00000000_00000001, //0x00000001 SealedID /**/= 0b_00000000_00000000_00000000_00000010, //0x00000002 Inherited /**/= 0b_00000000_00000000_00000000_00010000, //0x00000010 UI_IsAnimationProhibitedID /**/= 0b_00000000_00000000_00000000_00100000, //0x00000020 FW_AffectsMeasureID /**/= 0b_00000000_00000000_00000000_01000000, //0x00000040 FW_AffectsArrangeID /**/= 0b_00000000_00000000_00000000_10000000, //0x00000080 FW_AffectsParentMeasureID /**/= 0b_00000000_00000000_00000001_00000000, //0x00000100 FW_AffectsParentArrangeID /**/= 0b_00000000_00000000_00000010_00000000, //0x00000200 FW_AffectsRenderID /**/= 0b_00000000_00000000_00000100_00000000, //0x00000400 FW_OverridesInheritanceBehaviorID /**/= 0b_00000000_00000000_00001000_00000000, //0x00000800 FW_IsNotDataBindableID /**/= 0b_00000000_00000000_00010000_00000000, //0x00001000 FW_BindsTwoWayByDefaultID /**/= 0b_00000000_00000000_00100000_00000000, //0x00002000 FW_ShouldBeJournaledID /**/= 0b_00000000_00000000_01000000_00000000, //0x00004000 FW_SubPropertiesDoNotAffectRenderID /**/= 0b_00000000_00000000_10000000_00000000, //0x00008000 FW_SubPropertiesDoNotAffectRenderModifiedID= 0b_00000000_00000001_00000000_00000000, //0x00010000 FW_InheritsModifiedID /**/= 0b_00000000_00010000_00000000_00000000, //0x00100000 FW_OverridesInheritanceBehaviorModifiedID = 0b_00000000_00100000_00000000_00000000, //0x00200000 FW_ShouldBeJournaledModifiedID /**/= 0b_00000001_00000000_00000000_00000000, //0x01000000 FW_UpdatesSourceOnLostFocusByDefaultID /**/= 0b_00000010_00000000_00000000_00000000, //0x02000000 FW_DefaultUpdateSourceTriggerModifiedID/**/= 0b_00000100_00000000_00000000_00000000, //0x04000000 FW_ReadOnlyID /**/= 0b_00001000_00000000_00000000_00000000, //0x08000000 FW_DefaultUpdateSourceTriggerEnumBit1 /**/= 0b_01000000_00000000_00000000_00000000, //0x40000000 FW_DefaultUpdateSourceTriggerEnumBit2 /**/= 0b_10000000_00000000_00000000_00000000, //0x80000000 };注意以下三个属性,它们都是由
FrameworkPropertyMetadata
声明的,并且相互作用。即,IsDataBindingAllowed
并不等同于!IsNotDataBindable
;前者增加了一个附加限制,排除了“只读”属性使用错误绑定方向的情况。private bool ReadOnly => (_flags & FW_ReadOnlyID) != 0;
public bool IsDataBindingAllowed =>
(_flags & FW_IsNotDataBindableID) == 0 && !this.ReadOnly;
public bool IsNotDataBindable => (_flags & FW_IsNotDataBindableID) != 0;
[Flags]
public enum FrameworkPropertyMetadataOptions
{ // FPMO MetadataFlags
// ---------- ----------
// 0x00000010 ←┐
None /**/ = 0x00000000, // │
AffectsMeasure /**/ = 0x00000001, // << 6 0x00000040 │
AffectsArrange /**/ = 0x00000002, // << 6 0x00000080 │
AffectsParentMeasure /**/ = 0x00000004, // << 6 0x00000100 │
AffectsParentArrange /**/ = 0x00000008, // << 6 0x00000200 │
AffectsRender /**/ = 0x00000010, // << 6 0x00000400 │
Inherits /**/ = 0x00000020, // >> 1 → → ────┘
OverridesInheritanceBehavior /**/ = 0x00000040, // << 5 0x00000800
NotDataBindable /**/ = 0x00000080, // << 5 0x00001000
BindsTwoWayByDefault /**/ = 0x00000100, // << 5 0x00002000
Journal /**/ = 0x00000400, // << 4 0x00004000
SubPropertiesDoNotAffectRender /**/ = 0x00000800, // << 4 0x00008000
};