using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; using System.Collections; namespace Misc { public class BindingOperations { // 摘要: // 描述绑定中数据流的方向。 public enum BindingMode { // 摘要: // 导致对源属性或目标属性的更改可自动更新对方。此绑定类型适用于可编辑窗体或其他完全交互式 UI 方案。 TwoWay = 0, // // 摘要: // 当绑定源(源)更改时,更新绑定目标(目标)属性。如果要绑定的控件为隐式只读控件,则适用此绑定类型。例如,可以绑定到如股市代号之类的源。或者,可能目标属性没有用于进行更改(例如表的数据绑定背景色)的控件接口。如果不需要监视目标属性的更改,则使用 // System.Windows.Data.BindingMode.OneWay 绑定模式可避免 System.Windows.Data.BindingMode.TwoWay // 绑定模式的系统开销。 OneWay = 1 } /// <summary> /// 当绑定源(源)更改时,更新绑定目标(目标)属性 /// </summary> /// <param name="src"></param> /// <param name="srcPropertyName"></param> /// <param name="target"></param> /// <param name="targetPropertyName"></param> public static void SetBinding(INotifyPropertyChanged src, string srcPropertyName, INotifyPropertyChanged target, string targetPropertyName) { SetBinding(src, srcPropertyName, target, targetPropertyName, BindingMode.OneWay); } public static void SetBinding(INotifyPropertyChanged src, string srcPropertyName, IList target, int index) { Type type_s = src.GetType(); Type type_t = target.GetType(); System.Reflection.PropertyInfo pi_s = type_s.GetProperty(srcPropertyName); if (pi_s == null) return; object obj = pi_s.GetValue(src,null); target[index] = obj; src.PropertyChanged += (s, e) => { if (e.PropertyName == srcPropertyName) { object o = pi_s.GetValue(src, null); target[index] = obj; } }; } public static void SetBinding(INotifyPropertyChanged src, string srcPropertyName, Action func) { func(); src.PropertyChanged += (s, e) => { if (srcPropertyName==e.PropertyName) { func(); } }; } public static void SetBinding(INotifyPropertyChanged src, string[] srcPropertyNames, Action func) { func(); src.PropertyChanged += (s, e) => { if (srcPropertyNames.Contains(e.PropertyName)) { func(); } }; } public static void SetBinding(INotifyPropertyChanged src, string srcPropertyName, object target, Action func) { func(); PropertyChangedEventHandler pcevent; src.PropertyChanged += pcevent = (s, e) => { if (srcPropertyName == e.PropertyName) { func(); } }; if (IsMarkdownEvents) { if (!bindingConexts.ContainsKey(target)) { bindingConexts.Add(target, new List<PropertyChangedEventContexts>()); } var list = bindingConexts[target]; list.Add(new PropertyChangedEventContexts() { src = src, propertyChanged = pcevent }); } } public static void SetBinding(INotifyPropertyChanged src, string[] srcPropertyNames, object target, Action func) { func(); PropertyChangedEventHandler pcevent; src.PropertyChanged += pcevent = (s, e) => { if (srcPropertyNames.Contains(e.PropertyName)) { func(); } }; if (IsMarkdownEvents) { if (!bindingConexts.ContainsKey(target)) { bindingConexts.Add(target, new List<PropertyChangedEventContexts>()); } var list = bindingConexts[target]; list.Add(new PropertyChangedEventContexts() { src = src, propertyChanged = pcevent }); } } public class PropertyChangedEventContexts { public INotifyPropertyChanged src; public PropertyChangedEventHandler propertyChanged; } static Dictionary<object, List<PropertyChangedEventContexts>> bindingConexts; static bool IsMarkdownEvents = false; /// <summary> /// 开始记录事件 /// </summary> public static void StartMarkdownEvents(Dictionary<object, List<PropertyChangedEventContexts>> bindingConexts) { IsMarkdownEvents = true; BindingOperations.bindingConexts = bindingConexts; } /// <summary> /// 停止记录事件 /// </summary> public static void StopMarkdownEvents() { IsMarkdownEvents = false; BindingOperations.bindingConexts = null; } /// <summary> /// 释放事件目标对象 /// </summary> /// <param name="src"></param> public static void DisposeEventTargetObject(Dictionary<object, List<PropertyChangedEventContexts>> bindingConexts, object target) { if (!bindingConexts.ContainsKey(target)) return; var list = bindingConexts[target]; foreach(var context in list) { context.src.PropertyChanged -= context.propertyChanged; } bindingConexts.Remove(target); } /// <summary> /// 释放事件目标对象 /// </summary> /// <param name="src"></param> public static void DisposeEventTargetObject(Dictionary<object, List<PropertyChangedEventContexts>> bindingConexts) { foreach (var list in bindingConexts.Values) { foreach (var context in list) { context.src.PropertyChanged -= context.propertyChanged; } } bindingConexts.Clear(); } public static void SetBinding(INotifyPropertyChanged src, string srcPropertyName, INotifyPropertyChanged target, string targetPropertyName, BindingMode mode) { Type type_s = src.GetType(); Type type_t = target.GetType(); System.Reflection.PropertyInfo pi_s = type_s.GetProperty(srcPropertyName); System.Reflection.PropertyInfo pi_t = type_t.GetProperty(targetPropertyName); if (pi_s == null || pi_t == null) return; switch (mode) { case BindingMode.OneWay://src->target { object obj = pi_s.GetValue(src,null); pi_t.SetValue(target, obj, null); PropertyChangedEventHandler pcevent; src.PropertyChanged += pcevent = (s, e) => { if (e.PropertyName == srcPropertyName) { object o = pi_s.GetValue(src, null); pi_t.SetValue(target, o, null); } }; if (IsMarkdownEvents) { if (!bindingConexts.ContainsKey(target)) { bindingConexts.Add(target, new List<PropertyChangedEventContexts>()); } var list = bindingConexts[target]; list.Add(new PropertyChangedEventContexts() { src = src, propertyChanged = pcevent }); } }break; case BindingMode.TwoWay://src->target then target->src { object obj = pi_s.GetValue(src,null); pi_t.SetValue(target, obj, null); PropertyChangedEventHandler pcevent; src.PropertyChanged += pcevent = (s, e) => { if (e.PropertyName == srcPropertyName) { object o = pi_s.GetValue(s, null); pi_t.SetValue(target, o, null); } }; if (IsMarkdownEvents) { if (!bindingConexts.ContainsKey(target)) { bindingConexts.Add(target, new List<PropertyChangedEventContexts>()); } var list = bindingConexts[target]; list.Add(new PropertyChangedEventContexts() { src = src, propertyChanged = pcevent }); } target.PropertyChanged += pcevent = (s, e) => { if (e.PropertyName == targetPropertyName) { object o = pi_t.GetValue(s, null); pi_s.SetValue(src, o, null); } }; if (IsMarkdownEvents) { if (!bindingConexts.ContainsKey(src)) { bindingConexts.Add(src, new List<PropertyChangedEventContexts>()); } var list = bindingConexts[src]; list.Add(new PropertyChangedEventContexts() { src = target, propertyChanged = pcevent }); } } break; } } public static void SetBinding(INotifyPropertyChanged src, string srcPropertyName, ParamDictionary target, string targetPropertyName, BindingMode mode) { Type type_s = src.GetType(); System.Reflection.PropertyInfo pi_s = type_s.GetProperty(srcPropertyName); if (pi_s == null) return; switch (mode) { case BindingMode.OneWay://src->target { object obj = pi_s.GetValue(src, null); target.SetValue(targetPropertyName, obj); src.PropertyChanged += (s, e) => { if (e.PropertyName == srcPropertyName) { object o = pi_s.GetValue(src, null); target.SetValue(targetPropertyName, obj); } }; } break; case BindingMode.TwoWay://src->target then target->src { object obj = pi_s.GetValue(src, null); target.SetValue(targetPropertyName, obj); src.PropertyChanged += (s, e) => { if (e.PropertyName == srcPropertyName) { object o = pi_s.GetValue(s, null); target.SetValue(targetPropertyName, obj); } }; target.ValueChanged += (s, e) => { if (e.Key == targetPropertyName) { object o = target.GetValue(pi_s.PropertyType, targetPropertyName); pi_s.SetValue(src, o, null); } }; } break; } } } }