stu*_*rtd 8 c# data-binding functional-programming winforms
我正在研究使用扩展方法的强类型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;
}
}
Run Code Online (Sandbox Code Playgroud)
现在我可以像这样设置一个DataBinding:
txtBoundInt.DataBindings.Add<Contact>
(bindingSource, tb => tb.Text, contact => contact.Id);
Run Code Online (Sandbox Code Playgroud)
或这个:
cboBoundSelectedItem.DataBindings.Add
<Contact, ComboBox>
(bindingSource, cbo => cbo.SelectedItem, con => con.ContactType)
Run Code Online (Sandbox Code Playgroud)
尽管如此,似乎还有很多表达方式.有没有更好的办法?
编辑:我确实找到了一个更好的方法,但是我把这个问题改成了答案我遇到了麻烦 - 下面由@Carl_G转载.
将返回类型设置为对象怎么样?
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);
}
Run Code Online (Sandbox Code Playgroud)
由于问题已编辑为仅包含答案,我在此处包含该答案.作者可能应该单独留下原始问题并回答他自己的问题.但它似乎是一个非常好的解决方案.
编辑:我更喜欢这个我最终在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<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;
}
}
Run Code Online (Sandbox Code Playgroud)