Strong Typed Databinding

Win-Forms data-binding is done via a String parameter which specifies the member name to be bound, e.g.

// SOURCE DATA
class Person
{
    int Age { get; set; }
}

// SOME GUI APPLICATION
{
    // Create a TextBox and a Person.
    TextBox myTextBox = new TextBox();
    Person myPerson = new Person;
    myPerson.Age = 10;

    // Bind the age of that person to the textbox's text property.
    myTextBox.DataBindings.Add("Text", myPerson, "Age");
}

If a member name is changed (either manually or F2 – e.g), more often than not, the data-binding that is bound to that member will not be updated, the program will compile successfully, and the problem will not be found until run-time (hopefully found before the product is shipped). e.g. If we rename the Age property of the Person to AgeInYears, this program will compile successfully, but will fail at run-time.

Instead, it would be better if we could force the compiler to help us find these errors.

    // Instead of doing this.
    myTextBox.DataBindings.Add("Text", myPerson, "Age");

    // I would like to do this instead.
    myTextBox.Bind(tb => tb.Text).To(myPerson, p => p.Age);

With the aid of the PropertyNameHelper.GetPropertyName, we could do this with the following code.

public static class BindingHelper
{
    /// <summary>
    /// Returns a <c>BindingTarget</c> which can be used to bind a data source to a control.
    /// </summary>
    /// <typeparam name="T">The type of control to bind.</typeparam>
    /// <param name="controlToBind">The control to be bound.</param>
    /// <param name="expression">The expression representing the property of the control to bind to.</param>
    /// <returns>Returns the <c>BindingTarget</c> object which can be used to complete the binding process.</returns>
    public static BindingTarget Bind<T>(this T controlToBind, Expression<Func<T, object>> expression)
        where T : Control
    {
        // Simply return the binding target.
        return new BindingTarget(controlToBind, PropertyNameHelper.GetPropertyName<T>(expression));
    }
}

/// <summary>
/// Class that represents a control and property of the control, for data binding purposes.
/// </summary>
public class BindingTarget
{
    /// <summary>
    /// Creates a new <c>BindingTarget</c> instance.
    /// </summary>
    /// <param name="controlToBind">The control to bind to the data source.</param>
    /// <param name="propertyName">The property of the control to bind, to bind the data source to.</param>
    internal BindingTarget(Control controlToBind, string propertyName)
    {
        // Store away the control to be bound and the property name.
        this.controlToBind = controlToBind;
        this.controlPropertyName = propertyName;
    }

    /// <summary>
    /// Binds the <c>ControlToBind</c> to the data member of the specified data source.
    /// </summary>
    /// <typeparam name="T">The type of the data source to be bound to.</typeparam>
    /// <param name="dataSource">The data source to be bound to.</param>
    /// <param name="dataMemberExpression">The expression representing the data member of the data source to bind to.</param>
    public void To<T>(T dataSource, Expression<Func<T, object>> dataMemberExpression)
    {
        // Extract the name of the data member, (field or property), of the data source, from the expression.
        string data_member_name = PropertyNameHelper.GetPropertyName(dataMemberExpression);

        // Bind the control to be bound, to the data member of the data source.
        this.controlToBind.DataBindings.Clear();
        this.controlToBind.DataBindings.Add(this.controlPropertyName, dataSource, data_member_name);
    }

    /// <summary>
    /// The control to be bound to a data source.
    /// </summary>
    private Control controlToBind;

    /// <summary>
    /// The property name of the <c>ControlToBind</c> to bind the data source to.
    /// </summary>
    private string controlPropertyName;
}

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>