Строгая типизация привязки данных Windows Forms - PullRequest
8 голосов
/ 10 августа 2010

Я изучаю строго типизированную привязку данных Windows Forms с использованием методов расширения. Я получил такую ​​помощь от Ксавье , как показано ниже:

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;
    }
}

Теперь я могу настроить привязку данных следующим образом:

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

Или это:

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

Кажется, что происходит много приведений выражений. Есть ли лучший способ?


Редактировать: Я нашел лучший способ, но у меня возникли проблемы с заменой этого вопроса на этот ответ - он воспроизведен ниже автором @ Carl_G.

Ответы [ 3 ]

6 голосов
/ 25 сентября 2012

Поскольку вопрос был отредактирован так, чтобы включать только ответ, я включаю этот ответ здесь. Автор, вероятно, должен был оставить исходный вопрос в одиночестве и опубликовать ответ на свой вопрос. Но, похоже, это очень хорошее решение.


Редактировать: Я предпочитаю это решение, которое я в конечном итоге нашел в кеше 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;
    }
}
6 голосов
/ 10 августа 2010

Как насчет установки типа возвращаемого значения для объекта?

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);
}
2 голосов
/ 07 февраля 2012

Я использую код, опубликованный Стюартом, уже несколько месяцев.Я добавил еще несколько перегрузок, чтобы соответствовать остальным сценариям привязки данных, которые вы, возможно, захотите использовать (я просто выкладываю это здесь, чтобы другим было еще проще получить эту очень полезную работу)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...