工作中遇到silverlight本身没有提供的某些属性改变事件,但又需要在属性改变时得到通知,Google搬运stack overflow,原地址
/// Listen for change of the dependency property public void RegisterForNotification(string propertyName, FrameworkElement element, PropertyChangedCallback callback) { //Bind to a depedency property Binding b = new Binding(propertyName) { Source = element }; var prop = System.Windows.DependencyProperty.RegisterAttached( "ListenAttached"+propertyName, typeof(object), typeof(UserControl), new System.Windows.PropertyMetadata(callback)); element.SetBinding(prop, b); }
RegisterForNotification("Text", this.txtMain,(d,e)=>MessageBox.Show("Text changed")); RegisterForNotification("Value", this.sliderMain, (d, e) => MessageBox.Show("Value changed"));
更正:以上方法可能会造成回调方法callback内存泄漏,改为封装一个方法再调用callback
/// <summary> /// 监听任意依赖属性值改变事件的辅助方法 /// </summary> /// <param name="element"></param> /// <param name="propertyName"></param> /// <param name="callback"></param> public static void ListenForChange(FrameworkElement element, string propertyName, PropertyChangedCallback callback) { var b = new Binding(propertyName) { Source = element }; var prop = DependencyProperty.RegisterAttached("ListenAttached" + propertyName, typeof(object), typeof(FrameworkElement), new PropertyMetadata(new WeakPropertyChangedCallback(callback).PropertyChangedCallback)); element.SetBinding(prop, b); } /// <summary> /// 解决ListenForChange导致的内存泄漏: /// 避免DependencyProperty.RegisterAttached中元数据对PropertyChangedCallback的引用导致的内存泄漏 /// 但会导致WeakPropertyChangedCallback对象本身的泄漏,WeakPropertyChangedCallback对象本身不大,可以忽略 /// 即:以WeakPropertyChangedCallback对象的内存泄漏(很小) >>>===>>> 替代PropertyChangedCallback所在对象的内存泄漏(可能很大) /// /// TODO:暂时未找到其他的方式, DependencyProperty.RegisterAttached、PropertyMetadata缺少相关的清除方法 /// silverlight缺少BindingOperations.ClearBinding方法 /// </summary> class WeakPropertyChangedCallback { private WeakReference callback; public WeakPropertyChangedCallback(PropertyChangedCallback callback) { this.callback = new WeakReference(callback); } /// <summary> /// 转发到callback /// </summary> /// <param name="d"></param> /// <param name="e"></param> public void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (callback.IsAlive) { var cb = callback.Target as PropertyChangedCallback; if (cb != null) cb(d, e); } } }