ComboBox:向项添加文本和值(无绑定源)

ComboBox: Adding Text and Value to an Item (no Binding Source)

提问人:Bohn 提问时间:6/17/2010 最后编辑:RustyTheBoyRobotBohn 更新时间:10/8/2023 访问量:993806

问:

在 C# WinApp 中,如何将 Text 和 Value 添加到 ComboBox 的项中? 我做了一个搜索,通常答案是使用“绑定到源”..但就我而言,我的程序中没有准备好绑定源...... 我怎样才能做这样的事情:

combo1.Item[1] = "DisplayText";
combo1.Item[1].Value = "useful Value"
C# WinForms 组合框

评论


答:

16赞 Amr Elgarhy 6/18/2010 #1

这是刚刚想到的方法之一:

combo1.Items.Add(new ListItem("Text", "Value"))

要更改项目的文本或值,您可以这样做:

combo1.Items[0].Text = 'new Text';

combo1.Items[0].Value = 'new Value';

Windows 窗体中没有名为 ListItem 的类。它只存在于 ASP.NET 中,所以你需要在使用它之前编写自己的类,就像马科维茨在他的回答中所做的那样@Adam。

还要检查这些页面,它们可能会有所帮助:

评论

3赞 Adam Markowitz 6/18/2010
除非我弄错了,否则 ListItem 仅在 ASP.NET 中可用
0赞 Bohn 6/18/2010
是:(不幸的是,它只是在 ASP.net......那我现在能做什么呢?
0赞 JSON 12/1/2016
那么组合框中 SelectedValue 或 SelectedText 属性的意义何在?
418赞 Adam Markowitz 6/18/2010 #2

您必须创建自己的类类型并重写 ToString() 方法以返回所需的文本。下面是您可以使用的类的简单示例:

public class ComboboxItem
{
    public string Text { get; set; }
    public object Value { get; set; }

    public override string ToString()
    {
        return Text;
    }
}

以下是其用法的简单示例:

private void Test()
{
    ComboboxItem item = new ComboboxItem();
    item.Text = "Item text1";
    item.Value = 12;

    comboBox1.Items.Add(item);

    comboBox1.SelectedIndex = 0;

    MessageBox.Show((comboBox1.SelectedItem as ComboboxItem).Value.ToString());
}

评论

4赞 Amr Elgarhy 6/18/2010
我们真的需要这个新类 ComboboxItem 吗?我认为已经存在一个名为 ListItem 的。
19赞 Adam Markowitz 6/18/2010
我相信这可能只在 ASP.NET 中可用,而不能在 WinForms 中使用。
1赞 Adam Markowitz 6/18/2010
不。项目是一个单独的类型,仅用于存储项目的数据(文本、值、对其他对象的引用等)。它不是 ComboBox 的后代,而且非常罕见。
1赞 user2366842 10/17/2014
我知道我来晚了,但是我在纯 Windows 窗体环境中是如何做到这一点的,是设置一个数据表,向其添加项目,并将组合框绑定到数据表。有人会认为应该有一种更简洁的方法,但我还没有找到(DisplayMember 是您想要显示文本的组合框上的属性,ValueMember 是数据的值)
5赞 Alpha Gabriel V. Timbol 5/22/2016
我们如何获得“SelectedValue”或根据值选择项目...请回复
11赞 ChuckG 6/6/2012 #3

不知道这是否适用于原始帖子中给出的情况(不要介意这是两年后的事实),但这个例子对我有用:

Hashtable htImageTypes = new Hashtable();
htImageTypes.Add("JPEG", "*.jpg");
htImageTypes.Add("GIF", "*.gif");
htImageTypes.Add("BMP", "*.bmp");

foreach (DictionaryEntry ImageType in htImageTypes)
{
    cmbImageType.Items.Add(ImageType);
}
cmbImageType.DisplayMember = "key";
cmbImageType.ValueMember = "value";

若要读回值,必须将 SelectedItem 属性强制转换为 DictionaryEntry 对象,然后可以计算该对象的 Key 和 Value 属性。例如:

DictionaryEntry deImgType = (DictionaryEntry)cmbImageType.SelectedItem;
MessageBox.Show(deImgType.Key + ": " + deImgType.Value);
212赞 fab 8/1/2012 #4
// Bind combobox to a dictionary.
Dictionary<string, string> test = new Dictionary<string, string>();
        test.Add("1", "dfdfdf");
        test.Add("2", "dfdfdf");
        test.Add("3", "dfdfdf");
        comboBox1.DataSource = new BindingSource(test, null);
        comboBox1.DisplayMember = "Value";
        comboBox1.ValueMember = "Key";

// Get combobox selection (in handler)
string value = ((KeyValuePair<string, string>)comboBox1.SelectedItem).Value;

评论

4赞 Jeffrey Goines 2/4/2014
效果完美,这应该是选定的答案。但是我们不能使用 comboBox1.SelectedText 而不是 cast .SelectedItem 并取 .价值?
0赞 Smith 11/30/2014
@fab如何在组合框中找到带有特定键的项目
0赞 Dror 10/14/2016
是否可以根据字典键在组合框中选择一个项目?喜欢选择键 3,因此将选择键 3 的项目。
0赞 Plater 9/12/2019
此方法不再适用于 vs2015。引发的有关无法绑定到新 displaymember 和 Valuemember 的异常
137赞 buhtla 10/17/2012 #5

你可以像这样使用匿名类:

comboBox.DisplayMember = "Text";
comboBox.ValueMember = "Value";

comboBox.Items.Add(new { Text = "report A", Value = "reportA" });
comboBox.Items.Add(new { Text = "report B", Value = "reportB" });
comboBox.Items.Add(new { Text = "report C", Value = "reportC" });
comboBox.Items.Add(new { Text = "report D", Value = "reportD" });
comboBox.Items.Add(new { Text = "report E", Value = "reportE" });

更新:虽然上面的代码会正确地显示在组合框中,但你将无法使用 或 的属性。为了能够使用这些,请按如下方式绑定组合框:SelectedValueSelectedTextComboBox

comboBox.DisplayMember = "Text";
comboBox.ValueMember = "Value";

var items = new[] { 
    new { Text = "report A", Value = "reportA" }, 
    new { Text = "report B", Value = "reportB" }, 
    new { Text = "report C", Value = "reportC" },
    new { Text = "report D", Value = "reportD" },
    new { Text = "report E", Value = "reportE" }
};

comboBox.DataSource = items;

评论

17赞 Andrew 2/25/2015
我想稍微修改一下,因为程序员可能需要一个 for 循环。我没有使用数组,而是使用列表,然后我能够在循环中使用该方法。List<Object> items = new List<Object>();items.Add( new { Text = "report A", Value = "reportA" } );
1赞 Peter PitLock 5/9/2015
Andrew,您是否让 List<Object> 与 SelectedValue 属性一起使用?
0赞 Optavius 12/8/2016
@Venkat,comboBox.SelectedItem.GetType().GetProperty("Value").GetValue(comboBox.SelectedItem, null)
3赞 JPProgrammer 3/10/2017
@Venkat,如果使用设置 的第二个解决方案,则可以使用组合框的 or 属性,因此无需进行任何特殊强制转换。DataSourceSelectedValueSelectedText
2赞 Bill Pascoe 1/10/2013 #6

继 Adam Markowitz 的回答之后,这里有一种通用方法,可以(相对地)简单地将组合框的值设置为 ,同时向用户显示“Description”属性。(你可能会认为每个人都想这样做,这样它就会成为一个 .NET 的衬里,但事实并非如此,这是我发现的最优雅的方式)。ItemSourceenums

首先,创建以下简单类,用于将任何 Enum 值转换为 ComboBox 项:

public class ComboEnumItem {
    public string Text { get; set; }
    public object Value { get; set; }

    public ComboEnumItem(Enum originalEnum)
    {
        this.Value = originalEnum;
        this.Text = this.ToString();
    }

    public string ToString()
    {
        FieldInfo field = Value.GetType().GetField(Value.ToString());
        DescriptionAttribute attribute = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
        return attribute == null ? Value.ToString() : attribute.Description;
    }
}

其次,在事件处理程序中,需要将组合框的源设置为基于类型中每个的列表。这可以通过 Linq 实现。然后只需设置:OnLoadComboEnumItemsEnumEnumDisplayMemberPath

    void OnLoad(object sender, RoutedEventArgs e)
    {
        comboBoxUserReadable.ItemsSource = Enum.GetValues(typeof(EMyEnum))
                        .Cast<EMyEnum>()
                        .Select(v => new ComboEnumItem(v))
                        .ToList();

        comboBoxUserReadable.DisplayMemberPath = "Text";
        comboBoxUserReadable.SelectedValuePath= "Value";
    }

现在用户将从用户友好的列表中进行选择,但他们选择的将是您可以在代码中使用的值。 要访问用户在代码中的选择,将是 和 。DescriptionsenumcomboBoxUserReadable.SelectedItemComboEnumItemcomboBoxUserReadable.SelectedValueEMyEnum

7赞 Ryan 1/31/2013 #7
//set 
comboBox1.DisplayMember = "Value"; 
//to add 
comboBox1.Items.Add(new KeyValuePair("2", "This text is displayed")); 
//to access the 'tag' property 
string tag = ((KeyValuePair< string, string >)comboBox1.SelectedItem).Key; 
MessageBox.Show(tag);
3赞 Soenhay 3/5/2014 #8

使用 DataTable 的示例:

DataTable dtblDataSource = new DataTable();
dtblDataSource.Columns.Add("DisplayMember");
dtblDataSource.Columns.Add("ValueMember");
dtblDataSource.Columns.Add("AdditionalInfo");

dtblDataSource.Rows.Add("Item 1", 1, "something useful 1");
dtblDataSource.Rows.Add("Item 2", 2, "something useful 2");
dtblDataSource.Rows.Add("Item 3", 3, "something useful 3");

combo1.Items.Clear();
combo1.DataSource = dtblDataSource;
combo1.DisplayMember = "DisplayMember";
combo1.ValueMember = "ValueMember";

   //Get additional info
   foreach (DataRowView drv in combo1.Items)
   {
         string strAdditionalInfo = drv["AdditionalInfo"].ToString();
   }

   //Get additional info for selected item
    string strAdditionalInfo = (combo1.SelectedItem as DataRowView)["AdditionalInfo"].ToString();

   //Get selected value
   string strSelectedValue = combo1.SelectedValue.ToString();
4赞 Maggie 7/18/2014 #9

我喜欢 fab 的答案,但不想为我的情况使用字典,所以我用元组列表代替了。

// set up your data
public static List<Tuple<string, string>> List = new List<Tuple<string, string>>
{
  new Tuple<string, string>("Item1", "Item2")
}

// bind to the combo box
comboBox.DataSource = new BindingSource(List, null);
comboBox.ValueMember = "Item1";
comboBox.DisplayMember = "Item2";

//Get selected value
string value = ((Tuple<string, string>)queryList.SelectedItem).Item1;
22赞 cronynaval 11/20/2014 #10

您可以使用 Object 而不是创建自定义类来在 .DictionaryCombobox

在 Object 中添加键和值:Dictionary

Dictionary<string, string> comboSource = new Dictionary<string, string>();
comboSource.Add("1", "Sunday");
comboSource.Add("2", "Monday");

将源 Dictionary 对象绑定到:Combobox

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

检索密钥和值:

string key = ((KeyValuePair<string,string>)comboBox1.SelectedItem).Key;
string value = ((KeyValuePair<string,string>)comboBox1.SelectedItem).Value;

完整来源 : Combobox Text nd Value

2赞 Jan Staecker 2/26/2015 #11

您可以使用泛型类型:

public class ComboBoxItem<T>
{
    private string Text { get; set; }
    public T Value { get; set; }

    public override string ToString()
    {
        return Text;
    }

    public ComboBoxItem(string text, T value)
    {
        Text = text;
        Value = value;
    }
}

使用简单 int-Type 的示例:

private void Fill(ComboBox comboBox)
    {
        comboBox.Items.Clear();
        object[] list =
            {
                new ComboBoxItem<int>("Architekt", 1),
                new ComboBoxItem<int>("Bauträger", 2),
                new ComboBoxItem<int>("Fachbetrieb/Installateur", 3),
                new ComboBoxItem<int>("GC-Haus", 5),
                new ComboBoxItem<int>("Ingenieur-/Planungsbüro", 9),
                new ComboBoxItem<int>("Wowi", 17),
                new ComboBoxItem<int>("Endverbraucher", 19)
            };

        comboBox.Items.AddRange(list);
    }

评论

0赞 elle0087 11/7/2022
简直是最好的解决方案
0赞 Miguel 10/29/2015 #12

我遇到了同样的问题,我所做的是添加一个新索引,该索引中的值与第一个索引中的值相同,然后当我更改主要组合时,第二个索引中的索引同时更改,然后我取第二个组合的值并使用它。ComboBox

这是代码:

public Form1()
{
    eventos = cliente.GetEventsTypes(usuario);

    foreach (EventNo no in eventos)
    {
        cboEventos.Items.Add(no.eventno.ToString() + "--" +no.description.ToString());
        cboEventos2.Items.Add(no.eventno.ToString());
    }
}

private void lista_SelectedIndexChanged(object sender, EventArgs e)
{
    lista2.Items.Add(lista.SelectedItem.ToString());
}

private void cboEventos_SelectedIndexChanged(object sender, EventArgs e)
{
    cboEventos2.SelectedIndex = cboEventos.SelectedIndex;
}
1赞 Limitless isa 12/15/2015 #13

类创建:

namespace WindowsFormsApplication1
{
    class select
    {
        public string Text { get; set; }
        public string Value { get; set; }
    }
}

Form1 代码:

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            List<select> sl = new List<select>();
            sl.Add(new select() { Text = "", Value = "" });
            sl.Add(new select() { Text = "AAA", Value = "aa" });
            sl.Add(new select() { Text = "BBB", Value = "bb" });
            comboBox1.DataSource = sl;
            comboBox1.DisplayMember = "Text";
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {

            select sl1 = comboBox1.SelectedItem as select;
            t1.Text = Convert.ToString(sl1.Value);

        }

    }
}
0赞 Enigma 2/20/2016 #14

Visual Studio 2013 就是这样做的:This is how Visual Studio 2013 does it:

单项:

comboBox1->Items->AddRange(gcnew cli::array< System::Object^  >(1) { L"Combo Item 1" });

多个项目:

comboBox1->Items->AddRange(gcnew cli::array< System::Object^  >(3)
{
    L"Combo Item 1",
    L"Combo Item 2",
    L"Combo Item 3"
});

无需进行类覆盖或包含任何其他内容。是的,和 调用仍然有效。comboBox1->SelectedItemcomboBox1->SelectedIndex

0赞 Alex Smith 4/7/2016 #15

这与其他一些答案类似,但很紧凑,如果您已经有列表,则可以避免转换为字典。

给定一个 Windows 窗体上的“组合框”和一个具有 type 属性的类,ComboBoxSomeClassstringName

List<SomeClass> list = new List<SomeClass>();

combobox.DisplayMember = "Name";
combobox.DataSource = list;

这意味着 SelectedItem 是 中的对象,并且其中的每个项目都将使用其名称进行显示。SomeClasslistcombobox

评论

0赞 Matheus Rocha 4/5/2017
真!我以前用过...我总是忘记它的存在。在我关注这个属性之前,我已经习惯了我找到的解决方案,它并不总是有帮助。并非所有类都具有 or 属性,或者具有可任意用作显示文本的字符串属性。DisplayMemberNameTag
0赞 Alex Smith 4/6/2017
这是一个很好的观点。如果可以修改类,那么将这样的属性添加到类中可能是值得的,例如属性“ComboBoxText”(如果可用,可以返回 ToString() 方法)。或者,如果该类不可修改,则可以创建一个派生类,在该类中可以实现“ComboBoxText”属性。只有当您必须多次将类添加到 ComboBox 时,这才值得。否则,只需使用其他答案之一中解释的字典会更简单。
0赞 Matheus Rocha 4/6/2017
嘿亚历克斯,我已经用我通常在这些情况下使用的 ethod 做出了回答。我认为这与你说的很接近,或者我可能不明白你说的。我没有从类派生,因为有些类可能需要你实现我们不想重写的方法(所以我们会有一堆简单的方法),你还必须为每个不同的类型创建一个派生类你希望添加到组合框或列表框。我制作的类很灵活,您可以毫不费力地与任何类型一起使用。请看下面的答案,并告诉我您的想法:)base.Method();
0赞 Alex Smith 4/6/2017
我同意,您的答案似乎比为要添加到组合框中的每种类型创建派生类更方便。干得好!我想将来如果我没有像“名称”这样的属性,我将使用像你的答案或字典答案这样的东西:)
0赞 Esteban Verbel 7/6/2016 #16

对于Windows窗体来说,这是一个非常简单的解决方案,如果只需要一个(字符串)的最终值。项目的名称将显示在组合框上,并且可以轻松比较所选值。

List<string> items = new List<string>();

// populate list with test strings
for (int i = 0; i < 100; i++)
            items.Add(i.ToString());

// set data source
testComboBox.DataSource = items;

并在事件处理程序上获取所选值的值 (String)

string test = testComboBox.SelectedValue.ToString();
51赞 Mert Cingoz 9/28/2016 #17

您应该使用 object 在运行时解析组合框项。dynamic

comboBox.DisplayMember = "Text";
comboBox.ValueMember = "Value";

comboBox.Items.Add(new { Text = "Text", Value = "Value" });

(comboBox.SelectedItem as dynamic).Value

评论

2赞 Don Shrout 1/13/2018
这比创建一个单独的类并重写 ToString() 要好得多。
1赞 MickeyfAgain_BeforeExitOfSO 3/14/2018
dynamic 仅在 C# 4 及更高版本中可用。(我认为是 .NET 4.5)
0赞 Hannington Mambo 4/2/2018
编写简单快捷!我在 VB.net 中为 SelectedValue 执行了此操作:将值调暗为字符串 = CType(Me.SectionIDToComboBox.SelectedItem, Object)。价值
2赞 Dave Ludwig 2/28/2019
那么,如何使用“值”设置正确的组合框项目呢?
2赞 Ed Graham 11/4/2022
这个仍然是 2022 年(末)最简单的......
1赞 Muhammad Ahmad 2/14/2017 #18

您可以使用此代码将某些项目插入到包含文本和值的组合框中。

C#

private void ComboBox_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
{
    combox.Items.Insert(0, "Copenhagen");
    combox.Items.Insert(1, "Tokyo");
    combox.Items.Insert(2, "Japan");
    combox.Items.Insert(0, "India");   
}

XAML的

<ComboBox x:Name="combox" SelectionChanged="ComboBox_SelectionChanged_1"/>

评论

0赞 Vaibhav Bajaj 2/14/2017
请解释您的解决方案。
0赞 Muhammad Ahmad 7/8/2017
简单地说,将以下国家/地区添加到组合框中各自的索引中。当你运行它时。将出现一个组合框,其中包含一个索引为 0 的选项。如果单击组合框,将显示以下其他选项
2赞 Mr Heelis 11/28/2017
这对 ID 不起作用,这只是一种索引列表的方法,这不是问题所在
6赞 Matheus Rocha 4/5/2017 #19

如果有人仍然对此感兴趣,这里有一个简单而灵活的类,用于一个带有文本和任何类型的值的组合框项(与 Adam Markowitz 的示例非常相似):

public class ComboBoxItem<T>
{
    public string Name;
    public T value = default(T);

    public ComboBoxItem(string Name, T value)
    {
        this.Name = Name;
        this.value = value;
    }

    public override string ToString()
    {
        return Name;
    }
}

使用 the 比将 声明为 更好,因为 with 您必须跟踪用于每个项的类型,并将其强制转换为代码中以正确使用它。<T>valueobjectobject

我已经在我的项目中使用它很长一段时间了。这真的很方便。

4赞 Orhan Bayram 2/26/2018 #20

更好的解决方案;

Dictionary<int, string> userListDictionary = new Dictionary<int, string>();
        foreach (var user in users)
        {
            userListDictionary.Add(user.Id,user.Name);
        }

        cmbUser.DataSource = new BindingSource(userListDictionary, null);
        cmbUser.DisplayMember = "Value";
        cmbUser.ValueMember = "Key";

检索数据

MessageBox.Show(cmbUser.SelectedValue.ToString());

评论

0赞 MC9000 3/16/2020
虽然我能够填满组合框,但单击它会在 VS2019 中产生此错误 进行了 QueryInterface 调用,请求 COM 可见托管类“ComboBoxUiaProvider”的类接口
1赞 FAdao 10/18/2021 #21
using (SqlConnection con = new SqlConnection(insertClass.dbPath))
{
    con.Open();
    using (SqlDataAdapter sda = new SqlDataAdapter(
    "SELECT CategoryID, Category FROM Category WHERE Status='Active' ", con))
    {
        //Fill the DataTable with records from Table.
        DataTable dt = new DataTable();
        sda.Fill(dt);
        //Insert the Default Item to DataTable.
        DataRow row = dt.NewRow();
        row[0] = 0;
        row[1] = "(Selecione)";
        dt.Rows.InsertAt(row, 0);
        //Assign DataTable as DataSource.
        cboProductTypeName.DataSource = dt;
        cboProductTypeName.DisplayMember = "Category";
        cboProductTypeName.ValueMember = "CategoryID";
    }
}             
con.Close();