/// <summary> /// 设置绑定属性,一样是模拟微软的干活,只不过微软的这个方法不是在依赖对象里实现的, /// 而是在UIElement里实现的. /// </summary> /// <param name="p"></param> /// <param name="Binding"></param> public void SetBinding(MyDependencyProperty p, MyBinding Binding) { MyBinding theOld = null; //需要先将老的绑定找到并记录,因为需要解除挂接. if (_bindings.ContainsKey(p)) { theOld = _bindings[p]; _bindings[p] = Binding; } else { _bindings.Add(p, Binding); } //删除旧的绑定. if (theOld != null) { if (theOld.TargetObject is INotifyPropertyChanged) { ((INotifyPropertyChanged)theOld.TargetObject).PropertyChanged -= new PropertyChangedEventHandler(MyDependencyObject_PropertyChanged); } } //如果是单向绑定或者双向绑定则需要以下挂接。如果只是Onetime则不必要. if (Binding.TargetObject is INotifyPropertyChanged) { ((INotifyPropertyChanged)Binding.TargetObject).PropertyChanged += new PropertyChangedEventHandler(MyDependencyObject_PropertyChanged); } }
public void SetValue(MyDependencyProperty p, object val) { //如果设置值是默认值,则可不保存,以节省空间. object theOldValue = null; if (_dict.ContainsKey(p)) { theOldValue = _dict[p]; //如果已有设置值,且等于当前设置值,则退出 if (theOldValue == val) { return; } //如果设置值等于默认值,则删除已有的设置值。 if (p.DefaultValue == val) { _dict.Remove(p); return; } //设置新的字典值 _dict[p] = val; } else { //如果设置值不等于默认值,则增加设置值,否则不做任何设置。 if (p.DefaultValue != val) { _dict.Add(p, val); } else { return; } } if (p.PropertyMetadata != null && p.PropertyMetadata.PropertyChangedCallback != null) { MyDependencyPropertyChangedEventArgs theArgs = new MyDependencyPropertyChangedEventArgs(val, theOldValue, p); p.PropertyMetadata.PropertyChangedCallback(this, theArgs); } //如果是双向绑定,则需要同步数据到绑定数据源,这里假设需要双向绑定. if (_bindings.ContainsKey(p) == true) { MyBinding theBinding = _bindings[p]; if (theBinding.TargetObject != null && theBinding.PropertyName != "") { System.Reflection.PropertyInfo thePI = theBinding.TargetObject.GetType().GetProperty(theBinding.PropertyName); if (thePI != null && thePI.CanWrite == true) { //对于有索引的设置值比较复杂一点,可利用反射来进行,这里只是演示简单属性。 //注意,如果目标类实现了INotifyPropertyChanged接口,并有修改触发机制,那么这里的设置 //会触发目标属性改变事件,就会触发MyDependencyObject_PropertyChanged执行, //而MyDependencyObject_PropertyChanged里又调用了SetValue函数,这就会死循环,这也是 //为什么前面的代码中为什么要判断如果已经有的设置值等于当前设置新值直接退出的缘故,就是 //为了阻止死循环.当然,在目标属性中set里面做判断也可以,但这里一定要做, //原因大家可以自己想一下。 thePI.SetValue(theBinding.TargetObject, val, null); OnEvent(); } } } }