1

假设我有一个Order具有诸如 OrderName、OrderNum 等属性的类......

然后用这个类的项目列表填充 a ComboBox,假设我这样做:

comboBox1.DisplayMember = "OrderName";
comboBox1.ValueMember = "OrderNum";
comboBox1.DataSource = list.ToArray<Order>();

所以在这里我在代码中硬编码这些字段的名称,例如“OrderName”。有没有更好的方法来做到这一点,而不是硬编码字段的名称?它是否需要某种依赖注入技巧?你有什么建议?

4

4 回答 4

3

如果可能,您可以按照@JesseCSlicer 提到的方式进行操作,但如果您无法更改业务类,则可以采用以下方法:

基于这个SO answer,我们可以编写自己的助手:

public static class PropHelper<T>
{
    public static string PropName<R>(Expression<Func<T,R>> exp)
    {
        var mem = exp.Body as MemberExpression;
        if(mem != null) return mem.Member.Name;     
        throw new ArgumentException("Invlaid Property Name");
    }
}

并使用它:

comboBox1.DisplayMember = PropHelper<Order>.PropName(o => o.OrderName);
comboBox1.ValueMember = PropHelper<Order>.PropName(o => o.OrderNum);
comboBox1.DataSource = list.ToArray<Order>();
于 2012-09-25T17:21:37.423 回答
2

下面是我在几个 ASP.NET 应用程序中使用的修改后的类。我在您的示例中分配它的方式是这样的:

var orders = model.GetOrders(...);

comboBox1.DisplayMember = OrderQueryResults.DisplayMember;
comboBox1.ValueMember = OrderQueryResults.ValueMember;
comboBox1.DataSource = orders.Results;

班级:

public sealed class OrderQueryResults : IOrderQueryResults
{
    private const string DisplayName = "OrderName";

    private const string ValueName = "OrderNum";

    private readonly IEnumerable<IOrderQueryResult> results;

    private readonly object extra;

    private OrderQueryResults(IEnumerable<IOrderQueryResult> results, object extra)
    {
        this.results = results;
        this.extra = extra;
    }

    public string DisplayMember
    {
        get
        {
            return DisplayName;
        }
    }

    public string ValueMember
    {
        get
        {
            return ValueName;
        }
    }

    public IEnumerable<IOrderQueryResult> Results
    {
        get
        {
            return this.results;
        }
    }

    public object Extra
    {
        get
        {
            return this.extra;
        }
    }

    public static IOrderQueryResults Create(IEnumerable<IOrderQueryResult> results, object extra)
    {
        if (results == null)
        {
            throw new ArgumentNullException("results");
        }

        return new OrderQueryResults(results.ToList(), extra);
    }
}
于 2012-09-25T16:55:56.317 回答
2

这些只是 的属性Order,对吗?所以你可以使用const- 这比代码中的文字要好得多 - 但如果你愿意,你当然可以在运行时更改它们。你只需要知道它们是什么。

在您的类中,“OrderName”和“OrderNum”只是表示属性名称的字符串,因此如果您的类中碰巧有其他属性Order,您可以获取这些属性的名称并分配它们,例如,从某个用户行动。

如果你愿意,你可以使用反射来检查这个Order类。就像是:

Type theType =(typeof(Order));
// Get the public properties.
PropertyInfo[] thePropertyInfo =
    theType.GetProperties(BindingFlags.Public|BindingFlags.Instance);

要获取该 PropertyInfo 数组中任何特定属性的名称,您可以执行以下操作:

thePropertyInfo[i].Name;

会给你对象中第 i 个属性的名称。

因此,您可以说,将这些属性放入某个列表中,即其本身绑定到一个控件 - 例如 aComboBox然后在运行时选择将使用什么DisplayMemberValueMember然后只需设置这些属性,绑定就会自动更新。

于 2012-09-25T16:57:33.373 回答
0

最好使用放置在 Order 类中的 const 字符串,并在绑定数据源时在任何地方使用这些常量。

于 2012-09-25T16:47:48.120 回答