我正在研究使用扩展方法的强类型Windows窗体数据绑定。我得到了Xavier以下的帮助,如下所示:
using System;
using System.Linq.Expressions;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public static Binding Add<T>
(this ControlBindingsCollection dataBindings,
object dataSource,
Expression<Func<Control, object>> controlExpression,
Expression<Func<T, object>> objectExpression)
{
return Add(dataBindings, dataSource, controlExpression, objectExpression, false);
}
public static Binding Add<T>
(this ControlBindingsCollection dataBindings,
object dataSource,
Expression<Func<Control, object>> controlExpression,
Expression<Func<T, object>> objectExpression,
bool formattingEnabled)
{
string controlPropertyName = ProcessExpression(controlExpression.Body);
string bindingTargetName = ProcessExpression(objectExpression.Body);
return dataBindings
.Add(controlPropertyName, dataSource, bindingTargetName, formattingEnabled);
}
public static Binding Add<T, K>
(this ControlBindingsCollection dataBindings,
object dataSource,
Expression<Func<K, object>> controlExpression,
Expression<Func<T, object>> objectExpression)
{
return Add(dataBindings, dataSource, controlExpression, objectExpression, false);
}
public static Binding Add<T, K>
(this ControlBindingsCollection dataBindings,
object dataSource,
Expression<Func<K, object>> controlExpression,
Expression<Func<T, object>> 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<T, K>");
}
return propertyName;
}
}
现在我可以像这样设置一个DataBinding:
txtBoundInt.DataBindings.Add<Contact>
(bindingSource, tb => tb.Text, contact => contact.Id);
或者这个:
cboBoundSelectedItem.DataBindings.Add
<Contact, ComboBox>
(bindingSource, cbo => cbo.SelectedItem, con => con.ContactType)
虽然似乎有很多表达方式正在进行中。还有更好的方法吗?
编辑:我确实找到了一个更好的方法,但是我将这个问题更改为答案时遇到了麻烦 - @ reproduced below来自@Carl_G。
答案 0 :(得分:6)
如何将返回类型设置为object?
public static Binding Add<T>
(this ControlBindingsCollection dataBindings, object dataSource,
Expression<Func<Control, object>> controlLambda,
Expression<Func<T, object>> objectLambda) {
string controlPropertyName =
((MemberExpression)(controlLambda.Body)).Member.Name;
string bindingTargetName =
((MemberExpression)(objectLambda.Body)).Member.Name;
return dataBindings.Add
(controlPropertyName, dataSource, bindingTargetName);
}
答案 1 :(得分:6)
由于问题已编辑为仅包含答案,我在此处包含该答案。作者可能应该单独留下the original question并回答他自己的问题。但它似乎是一个非常好的解决方案。
编辑:我更喜欢这个我最终找到in Google's cache的解决方案(它已从author's site删除),因为它只需要一个类型规范。我不知道为什么原作者删除了它。
// 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<TControl, TDataSourceItem>
(this TControl control,
Expression<Func<TControl, object>> controlProperty,
object dataSource,
Expression<Func<TDataSourceItem, object>> dataSourceProperty)
where TControl: Control
{
return control.DataBindings.Add
(PropertyName.For(controlProperty),
dataSource,
PropertyName.For(dataSourceProperty));
}
}
public static class PropertyName
{
public static string For<T>(Expression<Func<T, object>> 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;
}
}
答案 2 :(得分:2)
我一直在使用Stuart发布的代码几个月了。我确实添加了一些重载来匹配你可能想要使用的其他数据绑定方案(我只是在这里发布,让其他人更容易让这个非常有用的工作)
public static class ControlExtensions {
/// <summary>Databinding with strongly typed object names</summary>
/// <param name="control">The Control you are binding to</param>
/// <param name="controlProperty">The property on the control you are binding to</param>
/// <param name="dataSource">The object you are binding to</param>
/// <param name="dataSourceProperty">The property on the object you are binding to</param>
public static Binding Bind<TControl, TDataSourceItem>(this TControl control, Expression<Func<TControl, object>> controlProperty, object dataSource, Expression<Func<TDataSourceItem, object>> dataSourceProperty)
where TControl :Control {
return control.DataBindings.Add(PropertyName.For(controlProperty), dataSource, PropertyName.For(dataSourceProperty));
}
public static Binding Bind<TControl, TDataSourceItem>(this TControl control, Expression<Func<TControl, object>> controlProperty, object dataSource, Expression<Func<TDataSourceItem, object>> dataSourceProperty, bool formattingEnabled = false)
where TControl :Control {
return control.DataBindings.Add(PropertyName.For(controlProperty), dataSource, PropertyName.For(dataSourceProperty), formattingEnabled);
}
public static Binding Bind<TControl, TDataSourceItem>(this TControl control, Expression<Func<TControl, object>> controlProperty, object dataSource, Expression<Func<TDataSourceItem, object>> 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<TControl, TDataSourceItem>(this TControl control, Expression<Func<TControl, object>> controlProperty, object dataSource, Expression<Func<TDataSourceItem, object>> 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<TControl, TDataSourceItem>(this TControl control, Expression<Func<TControl, object>> controlProperty, object dataSource, Expression<Func<TDataSourceItem, object>> 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<TControl, TDataSourceItem>(this TControl control, Expression<Func<TControl, object>> controlProperty, object dataSource, Expression<Func<TDataSourceItem, object>> 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<T>(Expression<Func<T, object>> 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;
}
}
}