using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace TemuKJD.Extension; public class DataContext : BindingSource { public DataContext() { } public DataContext(TSource dataSource) : base(dataSource, null) { } // 强类型的 DataSource,避免调用方还要自己转型 public new TSource DataSource { get => (TSource)base.DataSource; set => base.DataSource = value; } } public static class BindingExtensions { /// /// TSource 必须显式指定(因为无法从参数推断),TControl 自动从调用方控件推断 /// public static Binding Bind( this TControl ctrl, DataContext dataSource, Expression> controlPropertyExpr, Expression> dataPropertyExpr, DataSourceUpdateMode mode = DataSourceUpdateMode.OnPropertyChanged, string format = null, ConvertEventHandler parseHandler = null) where TControl : Control => BindCore(ctrl, controlPropertyExpr.GetPropertyName(), dataSource, dataPropertyExpr, mode, format, parseHandler); public static Binding Bind( this TControl ctrl, BindingSource dataSource, Expression> controlPropertyExpr, string dataPropertyName, DataSourceUpdateMode mode = DataSourceUpdateMode.OnPropertyChanged, string format = null, ConvertEventHandler parseHandler = null) where TControl : Control => BindCore(ctrl, controlPropertyExpr.GetPropertyName(), dataSource, dataPropertyName, mode, format, parseHandler); // ---------- 共享的核心实现,不对外暴露 ---------- private static Binding BindCore( Control ctrl, string controlPropertyName, BindingSource bs, Expression> dataPropertyExpr, DataSourceUpdateMode mode, string format, ConvertEventHandler parseHandler) => BindCore(ctrl, controlPropertyName, bs, dataPropertyExpr.GetPropertyName(), mode, format, parseHandler); private static Binding BindCore( Control ctrl, string controlPropertyName, BindingSource bs, string dataPropertyName, DataSourceUpdateMode mode, string format, ConvertEventHandler parseHandler) { var binding = new Binding(controlPropertyName, bs, dataPropertyName, true, mode); if (!string.IsNullOrEmpty(format)) binding.Format += (s, e) => e.Value = string.Format($"{{0:{format}}}", e.Value); if (parseHandler != null) binding.Parse += parseHandler; ctrl.DataBindings.Add(binding); return binding; } // ---------- TextBox ---------- public static Binding Bind( this TextBox ctrl, BindingSource bs, Expression> controlPropertyExpr, Expression> dataPropertyExpr, DataSourceUpdateMode mode = DataSourceUpdateMode.OnPropertyChanged, string format = null, ConvertEventHandler parseHandler = null) => BindCore(ctrl, controlPropertyExpr.GetPropertyName(), bs, dataPropertyExpr, mode, format, parseHandler); // ---------- CheckBox ---------- public static Binding Bind( this CheckBox ctrl, BindingSource bs, Expression> controlPropertyExpr, Expression> dataPropertyExpr, DataSourceUpdateMode mode = DataSourceUpdateMode.OnPropertyChanged, string format = null, ConvertEventHandler parseHandler = null) => BindCore(ctrl, controlPropertyExpr.GetPropertyName(), bs, dataPropertyExpr, mode, format, parseHandler); // ---------- DateTimePicker ---------- public static Binding Bind( this DateTimePicker ctrl, BindingSource bs, Expression> controlPropertyExpr, Expression> dataPropertyExpr, DataSourceUpdateMode mode = DataSourceUpdateMode.OnPropertyChanged, string format = null, ConvertEventHandler parseHandler = null) => BindCore(ctrl, controlPropertyExpr.GetPropertyName(), bs, dataPropertyExpr, mode, format, parseHandler); // ---------- ComboBox ---------- public static Binding Bind( this ComboBox ctrl, BindingSource bs, Expression> controlPropertyExpr, Expression> dataPropertyExpr, DataSourceUpdateMode mode = DataSourceUpdateMode.OnPropertyChanged, string format = null, ConvertEventHandler parseHandler = null) => BindCore(ctrl, controlPropertyExpr.GetPropertyName(), bs, dataPropertyExpr, mode, format, parseHandler); // ---------- NumericUpDown ---------- public static Binding Bind( this NumericUpDown ctrl, BindingSource bs, Expression> controlPropertyExpr, Expression> dataPropertyExpr, DataSourceUpdateMode mode = DataSourceUpdateMode.OnPropertyChanged, string format = null, ConvertEventHandler parseHandler = null) => BindCore(ctrl, controlPropertyExpr.GetPropertyName(), bs, dataPropertyExpr, mode, format, parseHandler); public static string GetPropertyName( this Expression> propertyExpr) { if (propertyExpr.Body is MemberExpression member) return member.Member.Name; // 处理值类型属性被隐式转换为 object 的情况(如 decimal -> object) if (propertyExpr.Body is UnaryExpression unary && unary.Operand is MemberExpression unaryMember) return unaryMember.Member.Name; throw new ArgumentException("表达式必须是形如 x => x.PropertyName 的属性访问", nameof(propertyExpr)); } }