强类型的Windows窗体数据绑定

我正在研究使用扩展方法的强类型Windows窗体数据绑定。 我从Xavier那里得到了以下的帮助,如下所示:

using System; using System.Linq.Expressions; using System.Windows.Forms; namespace WindowsFormsApplication1 { public static Binding Add (this ControlBindingsCollection dataBindings, object dataSource, Expression<Func> controlExpression, Expression<Func> objectExpression) { return Add(dataBindings, dataSource, controlExpression, objectExpression, false); } public static Binding Add (this ControlBindingsCollection dataBindings, object dataSource, Expression<Func> controlExpression, Expression<Func> objectExpression, bool formattingEnabled) { string controlPropertyName = ProcessExpression(controlExpression.Body); string bindingTargetName = ProcessExpression(objectExpression.Body); return dataBindings .Add(controlPropertyName, dataSource, bindingTargetName, formattingEnabled); } public static Binding Add (this ControlBindingsCollection dataBindings, object dataSource, Expression<Func> controlExpression, Expression<Func> objectExpression) { return Add(dataBindings, dataSource, controlExpression, objectExpression, false); } public static Binding Add (this ControlBindingsCollection dataBindings, object dataSource, Expression<Func> controlExpression, Expression<Func> objectExpression, bool formattingEnabled ) { string controlPropertyName = ProcessExpression(controlExpression.Body); string bindingTargetName = ProcessExpression(objectExpression.Body); return dataBindings.Add(controlPropertyName, dataSource, bindingTargetName, formattingEnabled); } private static string ProcessExpression(Expression expression) { string propertyName; if (expression is MemberExpression) { propertyName = ((MemberExpression) (expression)).Member.Name; } else if (expression is UnaryExpression) { propertyName = ((MemberExpression) ((UnaryExpression) (expression)).Operand).Member.Name; } else { throw new InvalidOperationException( "Unknown expression type error in DataBindingsExtensionMethods.Add"); } return propertyName; } } 

现在我可以像这样设置一个DataBinding:

 txtBoundInt.DataBindings.Add (bindingSource, tb => tb.Text, contact => contact.Id); 

或这个:

 cboBoundSelectedItem.DataBindings.Add  (bindingSource, cbo => cbo.SelectedItem, con => con.ContactType) 

尽管如此,似乎还有很多表达方式。 有没有更好的办法?


编辑:我确实找到了一个更好的方法,但是我把这个问题改成了答案我遇到了麻烦 – 下面由@Carl_G转载。

将返回类型设置为对象怎么样?

 public static Binding Add (this ControlBindingsCollection dataBindings, object dataSource, Expression> controlLambda, Expression> objectLambda) { string controlPropertyName = ((MemberExpression)(controlLambda.Body)).Member.Name; string bindingTargetName = ((MemberExpression)(objectLambda.Body)).Member.Name; return dataBindings.Add (controlPropertyName, dataSource, bindingTargetName); } 

由于问题已编辑为仅包含答案,我在此处包含该答案。 作者可能应该单独留下原始问题 ,并回答他自己的问题。 但它似乎是一个非常好的解决方案。


编辑:我更喜欢这个我最终在Google缓存中找到的解决方案(它已从作者的网站中删除),因为它只需要一种类型规范。 我不知道为什么原作者删除了它。

 // Desired call syntax: nameTextBox.Bind(t => t.Text, aBindingSource, (Customer c) => c.FirstName); // Binds the Text property on nameTextBox to the FirstName property // of the current Customer in aBindingSource, no string literals required. // Implementation. public static class ControlExtensions { public static Binding Bind (this TControl control, Expression> controlProperty, object dataSource, Expression> dataSourceProperty) where TControl: Control { return control.DataBindings.Add (PropertyName.For(controlProperty), dataSource, PropertyName.For(dataSourceProperty)); } } public static class PropertyName { public static string For(Expression> property) { var member = property.Body as MemberExpression; if (null == member) { var unary = property.Body as UnaryExpression; if (null != unary) member = unary.Operand as MemberExpression; } return null != member ? member.Member.Name : string.Empty; } } 

我一直在使用Stuart发布的代码几个月了。 我确实添加了一些重载以匹配您可能想要使用的其他数据绑定方案(我只是在这里发布给其他人以便更容易让这个非常有用的工作)

  public static class ControlExtensions { /// Databinding with strongly typed object names /// The Control you are binding to /// The property on the control you are binding to /// The object you are binding to /// The property on the object you are binding to public static Binding Bind(this TControl control, Expression> controlProperty, object dataSource, Expression> dataSourceProperty) where TControl :Control { return control.DataBindings.Add(PropertyName.For(controlProperty), dataSource, PropertyName.For(dataSourceProperty)); } public static Binding Bind(this TControl control, Expression> controlProperty, object dataSource, Expression> dataSourceProperty, bool formattingEnabled = false) where TControl :Control { return control.DataBindings.Add(PropertyName.For(controlProperty), dataSource, PropertyName.For(dataSourceProperty), formattingEnabled); } public static Binding Bind(this TControl control, Expression> controlProperty, object dataSource, Expression> dataSourceProperty, bool formattingEnabled, DataSourceUpdateMode updateMode) where TControl :Control { return control.DataBindings.Add(PropertyName.For(controlProperty), dataSource, PropertyName.For(dataSourceProperty), formattingEnabled, updateMode); } public static Binding Bind(this TControl control, Expression> controlProperty, object dataSource, Expression> dataSourceProperty, bool formattingEnabled, DataSourceUpdateMode updateMode, object nullValue) where TControl :Control { return control.DataBindings.Add(PropertyName.For(controlProperty), dataSource, PropertyName.For(dataSourceProperty), formattingEnabled, updateMode, nullValue); } public static Binding Bind(this TControl control, Expression> controlProperty, object dataSource, Expression> dataSourceProperty, bool formattingEnabled, DataSourceUpdateMode updateMode, object nullValue, string formatString) where TControl :Control { return control.DataBindings.Add(PropertyName.For(controlProperty), dataSource, PropertyName.For(dataSourceProperty), formattingEnabled, updateMode, nullValue, formatString); } public static Binding Bind(this TControl control, Expression> controlProperty, object dataSource, Expression> dataSourceProperty, bool formattingEnabled, DataSourceUpdateMode updateMode, object nullValue, string formatString, IFormatProvider formatInfo) where TControl :Control { return control.DataBindings.Add(PropertyName.For(controlProperty), dataSource, PropertyName.For(dataSourceProperty), formattingEnabled, updateMode, nullValue, formatString, formatInfo); } public static class PropertyName { public static string For(Expression> property) { var member = property.Body as MemberExpression; if(null == member) { var unary = property.Body as UnaryExpression; if(null != unary) member = unary.Operand as MemberExpression; } return null != member ? member.Member.Name : string.Empty; } } }