感谢Oliver让我入门,现在我有了一个既支持重构又是类型安全的解决方案。它也让我实现INotifyPropertyChanged,以便处理重命名的属性。
它的用法如下:
checkBoxCanEdit.Bind(c => c.Checked, person, p => p.UserCanEdit);textBoxName.BindEnabled(person, p => p.UserCanEdit);checkBoxEmployed.BindEnabled(person, p => p.UserCanEdit);trackBarAge.BindEnabled(person, p => p.UserCanEdit);textBoxName.Bind(c => c.Text, person, d => d.Name);checkBoxEmployed.Bind(c => c.Checked, person, d => d.Employed);trackBarAge.Bind(c => c.Value, person, d => d.Age);labelName.BindLabelText(person, p => p.Name);labelEmployed.BindLabelText(person, p => p.Employed);labelAge.BindLabelText(person, p => p.Age);
person类显示了如何以一种类型安全的方式实现INotifyPropertyChanged(或查看此答案以获取实现INotifyPropertyChanged的另一种相当不错的方法,ActiveSharp-
自动INotifyPropertyChanged也看起来不错):
public class Person : INotifyPropertyChanged{ private bool _employed; public bool Employed { get { return _employed; } set { _employed = value; onPropertyChanged(() => c.Employed); } } // etc private void onPropertyChanged(expression<Func<object>> property) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(BindingHelper.Name(property))); } } public event PropertyChangedEventHandler PropertyChanged;}WinForms绑定帮助程序类包含了使它们全部工作的基础:
namespace TypeSafeBinding{ public static class BindingHelper { private static string GetMemberName(expression expression) { // The nameof operator was implemented in C# 6.0 with .NET 4.6 // and VS2015 in July 2015. // The following is still valid for C# < 6.0 switch (expression.NodeType) { case expressionType.MemberAccess: var memberexpression = (Memberexpression) expression; var supername = GetMemberName(memberexpression.expression); if (String.IsNullOrEmpty(supername)) return memberexpression.Member.Name; return String.Concat(supername, '.', memberexpression.Member.Name); case expressionType.Call: var callexpression = (MethodCallexpression) expression; return callexpression.Method.Name; case expressionType.Convert: var unaryexpression = (Unaryexpression) expression; return GetMemberName(unaryexpression.Operand); case expressionType.Parameter: case expressionType.Constant: //Change return String.Empty; default: throw new ArgumentException("The expression is not a member access or method call expression"); } } public static string Name<T, T2>(expression<Func<T, T2>> expression) { return GetMemberName(expression.Body); } //NEW public static string Name<T>(expression<Func<T>> expression) {return GetMemberName(expression.Body); } public static void Bind<TC, TD, TP>(this TC control, expression<Func<TC, TP>> controlProperty, TD dataSource, expression<Func<TD, TP>> dataMember) where TC : Control { control.DataBindings.Add(Name(controlProperty), dataSource, Name(dataMember)); } public static void BindLabelText<T>(this Label control, T dataObject, expression<Func<T, object>> dataMember) { // as this is way one any type of property is ok control.DataBindings.Add("Text", dataObject, Name(dataMember)); } public static void BindEnabled<T>(this Control control, T dataObject, expression<Func<T, bool>> dataMember) { control.Bind(c => c.Enabled, dataObject, dataMember); } }}这利用了C#3.5中的许多新内容,并显示了可能的结果。现在,如果只有卫生宏,那么
Lisp程序员可能会停止称我们为二等公民)



