(原创)3.2 AddOwner和OverrideMetadata的区别
来源:互联网 发布:刘义军 知乎 编辑:程序博客网 时间:2024/05/01 13:17
1 AddOwner和OverrideMetadata
1.1 分析
从源代码上看,AddOwner函数中调用了OverrideMetadata, 并且把本类和依赖属性的哈希值加入到依赖属性的一张哈希列表private static Hashtable PropertyFromName中,哈希表的键值是用当前类类型的哈希值和依赖属性类类型的哈希值异或得到的,此表用来记录当前的依赖属性是属于哪个类的。
此哈希表很重要,因为在xaml解析器中,就是利用PropertyFromName表来分析依赖属性的。看到一片博客是这样说的,PropertyFromName hashtable is mainly use by the xaml => code process(翻译:PropertyFromName hashtable 主要用来从xaml到代码的转化的处理), which can be found by analyzing the DependencyProperty.FromName() method using reflector's "use by" fuction。
下边,我们主要介绍一下,OverrideMetadata函数是在干什么?查看源代码如下:
public DependencyProperty AddOwner(Type ownerType, PropertyMetadata typeMetadata) { if (ownerType == null) { throw new ArgumentNullException("ownerType"); } FromNameKey key = new FromNameKey(this.Name, ownerType);//获取hashcode lock (Synchronized) { if (PropertyFromName.Contains(key)) { throw new ArgumentException(MS.Internal.WindowsBase.SR.Get("PropertyAlreadyRegistered", new object[] { this.Name, ownerType.Name })); } } if (typeMetadata != null) { this.OverrideMetadata(ownerType, typeMetadata);//@1 进入OverrideMetaData } lock (Synchronized) { PropertyFromName.set_Item(key, this);//PropertyFromName hashtable } return this; }在OverrideMetadata中代码嵌套多,直接写出有用的代码
DependencyObjectType dType = DependencyObjectType.FromSystemType(forType); PropertyMetadata baseMetadata = this.GetMetadata(dType.BaseType);//dType.BaseType表示继承体系中的父类;例如,AnimalButton类BaseType表示的Button;获取GetMetadata的规则,可以查看《附加属性原理》的1.1.1.1中的分析:大概就是如果本继承体系中没有,就直接选取_defaultMetadata作为元数据; if (baseMetadata.PropertyChangedCallback != null) { Delegate[] invocationList = baseMetadata.PropertyChangedCallback.GetInvocationList(); if (invocationList.Length > 0) { System.Windows.PropertyChangedCallback a = (System.Windows.PropertyChangedCallback) invocationList[0]; for (int i = 1; i < invocationList.Length; i++) { a = (System.Windows.PropertyChangedCallback) Delegate.Combine(a, (System.Windows.PropertyChangedCallback) invocationList[i]); } a = (System.Windows.PropertyChangedCallback) Delegate.Combine(a, this._propertyChangedCallback); this._propertyChangedCallback = a; } }//合并PropertyMetaChanged的事件响应 if (this._coerceValueCallback == null) { this._coerceValueCallback = baseMetadata.CoerceValueCallback;//直接覆盖,如果提供,什么都不做 } if (this._freezeValueCallback == null) { this._freezeValueCallback = baseMetadata.FreezeValueCallback; }
1.2 举例
我们可以得到这样的结论,AddOwner不是依赖属性或者附加属性的专利,OverrideMetadata也不是。其中,AddOwner是OverrideMetadata和添加PropertyFromName哈希表的合集,OverrideMetadata是把当前元数据和继承体系中最近的父类的依赖属性的元数据PropertyChangedCallback进行合并,CoerceCallback进行取舍。下边附上一例:例子:
public class Feeling : DependencyObject { //注册Dependency Property public static readonly DependencyProperty FeelProperty = DependencyProperty.Register("Feel", typeof(string), typeof(Feeling), new PropertyMetadata("feel-happy", new PropertyChangedCallback(FeelChanged))); private static void FeelChanged(object sender, DependencyPropertyChangedEventArgs e) { Trace.WriteLine("the feel is changed, new Value is " + e.NewValue.ToString()); } //注册Attached Property public static readonly DependencyProperty SenseProperty = DependencyProperty.RegisterAttached("Sense", typeof(string), typeof(Feeling), new PropertyMetadata("sense-happy", new PropertyChangedCallback(SenseChanged))); private static void SenseChanged(object sender, DependencyPropertyChangedEventArgs e) { Trace.WriteLine("the sense is changed, new value is " + e.NewValue.ToString()); //Window window = new Window(); //window.Title = sender.GetType().ToString(); //window.Show(); } public static string GetSense(DependencyObject dO) { return dO.GetValue(SenseProperty) as string; } public static void SetSense(DependencyObject dO, string val) { dO.SetValue(SenseProperty, val); } } public class AnimalButton : Button { //在 dependency property addowner调用,propertyFromName[key] = this; //具体有什么用处 //key = ownerType ^ propertyname //如果AddOwner了附加依赖属性,那么, public static readonly DependencyProperty SenseProperty = Feeling.SenseProperty.AddOwner(typeof(AnimalButton), new PropertyMetadata("add owner animal button", new PropertyChangedCallback(AnimalButtonSensePropertyChanged))); private static void AnimalButtonSensePropertyChanged(object sender, DependencyPropertyChangedEventArgs e) { Trace.WriteLine("AnimalButton SenseProperty changed, new value is " + e.NewValue.ToString()); } public string Sense { get { return GetValue(SenseProperty) as string; } set { SetValue(SenseProperty, value); } } private static void AnimalButtonFeelPropertyChanged(object sender, DependencyPropertyChangedEventArgs e) { Trace.WriteLine("AnimalButton FeelProperty Changed, new value is " + e.NewValue.ToString()); } public static readonly DependencyProperty FeelProperty = Feeling.FeelProperty.AddOwner(typeof(AnimalButton), new PropertyMetadata(("add owner animal FeelProperty"), new PropertyChangedCallback(AnimalButtonFeelPropertyChanged))); public string Feel { get { return GetValue(FeelProperty) as string; } set { SetValue(FeelProperty, value); } } }
<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:loc="clr-namespace:WpfApplication1" Title="MainWindow" Height="350" Width="525"> <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <TextBox Grid.Row="0" x:Name="textBox" FontSize="32"></TextBox> <loc:AnimalButton Grid.Row="1" Content="Button" Click="AnimalButton_Click" Feel="{Binding SenseString, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type loc:MainWindow}}}" Sense="{Binding SenseString, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type loc:MainWindow}}}"/> </Grid></Window>
public partial class MainWindow : Window,INotifyPropertyChanged { public MainWindow() { InitializeComponent();// DependencyObjectType dt = DependencyObjectType.FromSystemType(typeof(Window));// DependencyObjectType dtt = DependencyObjectType.FromSystemType(typeof(AnimalButton));// DependencyObjectType dType = DependencyObjectType.FromSystemType(typeof(AnimalButton));// DependencyObjectType baseType = dType.BaseType;//获取当前依赖属性的父类中的对应的MetaData;// PropertyMetadata baseMetadata = Feeling.SenseProperty.GetMetadata(baseType);// int xx = 0; } private string _senseString = "main window"; public string SenseString { get { return _senseString; } set { if (value != _senseString) { _senseString = value; Notify("SenseString"); } } } public event PropertyChangedEventHandler PropertyChanged; void Notify(string name) { var handler = this.PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(name)); } } private void AnimalButton_Click(object sender, RoutedEventArgs e) { SenseString = textBox.Text; } }
将会打印出
AnimalButton FeelProperty Changed, new value is RenDawei - 说明如果是依赖属性,OverrideMetadata的时候,获取的_defaultMetadata没有PropertyChanged回调函数,而附加依赖属性是有的;
the sense is changed, new value is RenDawei
AnimalButton SenseProperty changed, new value is RenDawei
- (原创)3.2 AddOwner和OverrideMetadata的区别
- setTimeout 和 setInterval 的区别[原创修正]
- 【原创】aspx和html之间的区别
- 【原创】unset和null的区别
- 原创 进程和线程的区别
- 【原创】MyISAM和InnoDB的order by的区别
- 原创:异常处理方式的区别和分析
- 【原创】链接中 href='#' 和 href='###' 的区别
- 【原创】Scrum中Product Backlog和Sprint Backlog的区别
- memcpy和memmove的区别(实验代码原创)
- [乐意黎原创]JS中null和undefined的区别
- java原创和非原创的视频
- 抽象类和接口在语法和设计原则上的区别(原创,转载注明出处)
- (原创)分词的被动语态中现在式和过去式的区别
- 20岁MM和25岁MM的区别(非原创,分享贴)
- C语言堆栈入门——堆和栈的区别【顶嵌原创】
- C语言堆栈入门——堆和栈的区别【顶嵌原创】
- C语言堆栈入门——堆和栈的区别【顶嵌原创】
- ffmpeg解码jpg并编码成h264
- UVA 1356/ ZOJ 2614 Bridge 弧长积分+二分
- luence之全文检索
- POJ 1903 & ZOJ 2469 & UVA 1326 Jurassic Remains (部分枚举)
- 京东商城发现了一枚Bug
- (原创)3.2 AddOwner和OverrideMetadata的区别
- HBase安装
- Android应用开发学习笔记之菜单
- Ubuntu11.04更新源(转)
- hdu 4006 The kth great number(优先队列)
- LeetCode-Path Sum
- SpringMVC+mybatis+DWR3注解
- 【xinfanqie】笔者分享:教你如何快速关闭磁盘索引
- java先序中序建立二叉树的递归算法