views:

86

answers:

1

Edit: I prefer this solution I found eventually in Google's cache (it has been deleted from the author's site) as it only needs one type specification and does it in a way I haven't seen before. I don't know why the original author deleted it.

// 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;
    }
}
+3  A: 

What about setting the return type to 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);
}
Xavier Poinas
Thanks: that compiles, but yields this runtime error: Unable to cast object of type 'System.Linq.Expressions.UnaryExpression' to type 'System.Linq.Expressions.MemberExpression'.
Stuart Dunkeld
Hmm. I can cast the objectLambda to a UnaryExpression, but I can't see how to get the property name from the UnaryExpression.. (the controlLambda is still a MemberExpression)
Stuart Dunkeld
I'd like to nominate the MSDN UnaryExpression page as 'least useful MSDN page ever' in a very crowded field - http://msdn.microsoft.com/en-us/library/system.linq.expressions.unaryexpression.aspx
Stuart Dunkeld
@Xavier Many thanks for your help, that's it nailed now.
Stuart Dunkeld