如何创建一个带有标签和值的Winforms组合框?

40

我主要是一个ASP.NET开发人员,但我正在开发一个WinForms应用程序,并注意到ASP.NET组合框(HTML选择器)与WinForms的巨大差异。我发现(可能不正确),WinForm的组合框只有一个“标签”,而ASP.NET允许您指定“标签”和“值”。

我想使用带有标签和值(Foobar / 42329)的WinForms组合框(或其他可比较的控件)。这是可能的吗?我已经尝试搜索答案,但没有得到太多结果。如果无法实现该功能,如何设计WinForm组合框来表示具有其关联数据库ID的城市?

  • 多伦多 / 2324
  • 蒙特利尔 / 64547
  • 温哥华 / 1213

如果您没有使用绑定,可以使用此链接:http://support.microsoft.com/kb/319946,否则请使用Marc的答案。 - Jeremy Thompson
6个回答

53

我能想到几种方法:

  • 重写City类的ToString()方法,将其设为 return Name + " / " + Id;
  • 同上,但使用TypeConverter
  • 添加一个DisplayText属性并返回相同的结果,然后使用DisplayMember
  • 构建一个用于数据的桥接类

对于最后一种方法:

var data = cities.Select(city => new {
     Id = city.Id, Text = city.Name + " / " + city.Id }).ToList();
cbo.ValueMember = "Id";
cbo.DisplayMember = "Text";
cbo.DataSource = data;

2
我从未想过组合框如此强大... 我也是一个 Linq 新手,决定走这条路线并采用了这个解决方案。Stackoverflow 真是太棒了,谢谢大家! - nokturnal
1
看起来有点琐碎,但是“Id = city.Id”可以简化为只写成“city.Id”,因为如果没有指定属性设置器的名称,.Net将使用属性设置器的名称。 - Arbiter
5
@Arbiter 是的,我知道;我只是喜欢说得清楚明白... 这样在我重命名东西时就可以避免出现意外了;p - Marc Gravell
无关紧要的评论,但我刚刚被咬了 - .ToList() 部分很重要,否则在运行时对 DataSource 的赋值将失败。 - Marcel Popescu

41

假设您的值是唯一的,您可以首先填充一个字典,然后将ComboBox绑定到该字典。不幸的是,数据绑定需要一个IList或IListSource,因此您必须将其包装在Binding Source中。我在这里找到了解决方案here

    private void PopulateComboBox()
    {
        var dict = new Dictionary<int, string>();
        dict.Add(2324, "Toronto");
        dict.Add(64547, "Vancouver");
        dict.Add(42329, "Foobar");

        comboBox1.DataSource = new BindingSource(dict, null);
        comboBox1.DisplayMember = "Value";
        comboBox1.ValueMember = "Key";
    }

你好,你怎么在VB中实现这个?我在编译时没有错误,但在运行时出错了。 - Aivan Monceller
3
需要在定义数据源之前分配 DisplayMember 和 ValueMember。 - Chris Watts
@CJxD 不,他们不会,在Windows Forms中至少不会。 - Jamie Ide

7
你可以尝试创建一个名为ComboBoxItem的小类,如下所示:
public class ComboBoxItem<T>
{
    public string Label { get; set; }
    public T Value { get; set; }

    public override string ToString()
    {
        return Label ?? string.Empty;
    }
}

当你需要获取一个对象时,只需将其转换为ComboBoxItem


为什么你要在字符串上调用 ToString - SLaks
3
他重写了 "ToString" 方法,以确保它永远不会返回 null。 - EricLaw

5

可以通过设置 ComboBox 的 DataSource 属性将其绑定到对象集合。

默认情况下,SelectedValue 属性将给出所选对象,并且列表将调用每个对象的 ToString 方法并显示结果。
但是,如果设置了 ComboBox 的 DisplayMember 属性,则列表将显示 DisplayMember 中命名的属性的值。类似地,您可以设置 ComboBox 的 ValueMember 属性,SelectedValue 属性将返回 ValueMember 命名的属性的值。


因此,您需要将 ComboBox 绑定到具有 NameValue 属性的对象列表。
然后,您可以将 ComboBox 的 [DisplayMember] 属性设置为 [Name],将 [ValueMember] 属性设置为 [Value]。

编辑: 您还可以调用 Add 方法并向其提供此类对象,而不是数据绑定。或者,您可以将其绑定到 List<T> 或数组。


有没有一种方法可以在不使用数据绑定的情况下完成这个任务?我正在手动向组合框中添加项目。 - nokturnal
如果您设置了组合框的ValueMember / DisplayMember属性,则无需进行数据绑定。即使您使用combobox.Add(yourobject),它也应该使用它们。但是需要注意的是,您仍然需要一个名称/值对象。 - Joshua Cauble

2

有一个叫做DisplayMember的属性,它的值将用于显示,还有一个ValueMember属性,它是用于值的属性。


1
        anestezi.DisplayMember = "Text";
        anestezi.ValueMember = "Value";
        anestezi.DataSource = new[] { 
            new { Text = "Genel", Value = "G" }, 
            new { Text = "Lokal", Value = "L" },
            new { Text = "Sedasyon", Value = "S" }
        };
        anestezi.SelectedIndex = 0;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接