【问题标题】:ComboBox: Adding Text and Value to an Item (no Binding Source)ComboBox:向项目添加文本和值(无绑定源)
【发布时间】:2026-01-08 06:00:01
【问题描述】:

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

combo1.Item[1] = "DisplayText";
combo1.Item[1].Value = "useful Value"

【问题讨论】:

    标签: c# winforms combobox


    【解决方案1】:

    您必须创建自己的类类型并覆盖 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());
    }
    

    【讨论】:

    • 我们真的需要这个新类 ComboboxItem 吗?我认为已经存在一个名为 ListItem。
    • 我相信它可能只在 ASP.NET 中可用,而在 WinForms 中不可用。
    • 没有。 item 是一个单独的类型,仅用于存储 item 的数据(文本、值、对其他对象的引用等)。它不是 ComboBox 的后代,而且非常罕见。
    • 我知道我参加聚会有点晚了,但我在纯 Windows 窗体环境中这样做的方法是设置一个数据表,向其中添加项目,并将组合框绑定到数据表。有人会认为应该有一种更清洁的方法,但我还没有找到(DisplayMember 是您想要显示文本的组合框上的属性,ValueMember 是数据的值)
    • 我们如何获取“SelectedValue”或根据值选择项目...请回复
    【解决方案2】:
    // Bind combobox to 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;
    

    【讨论】:

    • 完美运行,这应该是选择的答案。但是我们不能使用 comboBox1.SelectedText 而不是强制转换 .SelectedItem 并取 .Value 吗?
    • @fab 你如何使用某个键在组合框中找到项目
    • 是否可以根据字典键选择组合框中的项目?就像选择键 3 这样带有键 3 的项目将被选中。
    • 此方法不再适用于 vs2015。无法绑定到新的 displaymember 和 Valuemember 引发的异常
    【解决方案3】:

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

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

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

    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;
    

    【讨论】:

    • 我想稍微修改一下,因为程序员可能还需要一个 for 循环。我使用列表 List&lt;Object&gt; items = new List&lt;Object&gt;(); 而不是数组,然后我可以在循环中使用方法 items.Add( new { Text = "report A", Value = "reportA" } );
    • 安德鲁,您是否让 List 与 SelectedValue 属性一起使用?
    • @Venkat,comboBox.SelectedItem.GetType().GetProperty("Value").GetValue(comboBox.SelectedItem, null)
    • @Venkat 如果您使用设置DataSource 的第二种解决方案,您可以使用组合框的SelectedValueSelectedText 属性,因此无需进行任何特殊转换。
    【解决方案4】:

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

    comboBox.DisplayMember = "Text";
    comboBox.ValueMember = "Value";
    
    comboBox.Items.Add(new { Text = "Text", Value = "Value" });
    
    (comboBox.SelectedItem as dynamic).Value
    

    【讨论】:

    • 这比创建一个单独的类并覆盖 ToString() 要好得多。
    • dynamic 仅在 C# 4 及更高版本中可用。 (我认为是 .NET 4.5)
    • 写起来简单快捷!我在 VB.net 中为 SelectedValue 执行此操作: Dim Value As String = CType(Me.SectionIDToComboBox.SelectedItem, Object).Value
    • 那么,如何使用“值”设置正确的组合框项?
    【解决方案5】:

    您可以使用Dictionary Object 而不是创建自定义类来在Combobox 中添加文本和值。

    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

    【讨论】:

      【解决方案6】:

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

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

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

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

      Windows Forms 中没有名为 ListItem 的类。它只存在于ASP.NET 中,因此您需要在使用它之前编写自己的类,就像@Adam Markowitz 在his answer 中所做的一样。

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

      【讨论】:

      • 除非我弄错了,ListItem 只在 ASP.NET 中可用
      • 是的 :( 不幸的是它只在 ASP.net 中......所以我现在该怎么办?
      • 那么组合框中的 SelectedValue 或 SelectedText 属性的意义何在?
      【解决方案7】:

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

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

      【讨论】:

        【解决方案8】:
        //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);
        

        【讨论】:

          【解决方案9】:

          如果还有人对此感兴趣,这里有一个简单而灵活的组合框项目类,它包含文本和任何类型的值(非常类似于 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;
              }
          }
          

          使用&lt;T&gt; 比将value 声明为object 更好,因为使用object,您必须跟踪您用于每个项目的类型,并将其转换为您的代码正确使用它。

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

          【讨论】:

            【解决方案10】:

            我喜欢 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;
            

            【讨论】:

              【解决方案11】:

              使用 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();
              

              【讨论】:

                【解决方案12】:

                你可以使用泛型类型:

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

                【讨论】:

                  【解决方案13】:

                  进一步了解 Adam Markowitz 的回答,这是一种通用方法(相对),只需将组合框的 ItemSource 值设置为 enums,同时向用户显示“描述”属性。 (你会认为每个人都想这样做,这样它就会成为一个 .NET 一个班轮,但事实并非如此,这是我发现的最优雅的方式。

                  首先,创建这个简单的类,用于将任何 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;
                      }
                  }
                  

                  其次,在OnLoad 事件处理程序中,您需要根据Enum 类型中的每个Enum 将组合框的源设置为ComboEnumItems 列表。这可以通过 Linq 来实现。然后只需设置DisplayMemberPath:

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

                  现在用户将从您的用户友好列表中选择Descriptions,但他们选择的将是您可以在代码中使用的enum 值。 要在代码中访问用户的选择,comboBoxUserReadable.SelectedItem 将是 ComboEnumItemcomboBoxUserReadable.SelectedValue 将是 EMyEnum

                  【讨论】:

                    【解决方案14】:

                    这里有更好的解决方案;

                    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());
                    

                    【讨论】:

                    • 虽然我能够填充组合框,但单击它会在 VS2019 中产生此错误 A QueryInterface call was made requesting the class interface of COM visible managed class 'ComboBoxUiaProvider
                    【解决方案15】:

                    类创建:

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

                    【讨论】:

                      【解决方案16】:

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

                      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"/>
                      

                      【讨论】:

                      • 请解释您的解决方案。
                      • 简单地说,在combox的各自索引中添加以下国家。当你运行它时。出现一个组合框,其中一个选项位于 0 索引处。如果单击该组合框,则会显示以下其他选项
                      • 这对 id 不起作用,这只是索引列表的一种方式,这不是问题所在
                      【解决方案17】:

                      我遇到了同样的问题,我所做的是添加一个新的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;
                      }
                      

                      【讨论】:

                        【解决方案18】:

                        这就是 Visual Studio 2013 的做法:

                        单件:

                        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-&gt;SelectedItemcomboBox1-&gt;SelectedIndex 调用仍然有效。

                        【讨论】:

                          【解决方案19】:

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

                          给定一个 Windows 窗体上的 ComboBox“组合框”和一个具有 string 类型属性 Name 的类 SomeClass

                          List<SomeClass> list = new List<SomeClass>();
                          
                          combobox.DisplayMember = "Name";
                          combobox.DataSource = list;
                          

                          这意味着 SelectedItem 是来自listSomeClass 对象,combobox 中的每个项目都将使用其名称显示。

                          【讨论】:

                          • 真的!我以前用过DisplayMember...我总是忘记它的存在。在我关注这个属性之前,我已经习惯了我找到的解决方案,而且它并不总是有帮助。并非所有类都有NameTag 属性,或者具有可以任意用作显示文本的字符串属性。
                          • 这是一个很好的观点。如果您可以修改类,那么将这样的属性添加到类中可能是值得的,例如属性“ComboBoxText”(如果可用,它可以返回 ToString() 方法)。或者,如果该类不可修改,则可以创建一个派生类,其中可以实现“ComboBoxText”属性。只有当您必须多次将类添加到 ComboBox 时,这才是值得的。否则,只使用字典会更简单,如其他答案之一所述。
                          • 嗨,Alex,我已经用我通常在这些情况下使用的方法做出了回答。我认为这与您所说的非常接近,或者我可能不明白您所说的。我不是从该类派生的,因为某些类可能要求您实现我们不想覆盖的方法(因此我们会有一堆带有简单 base.Method(); 的方法),您还必须创建您希望添加到组合框或列表框的每种不同类型的派生类。我制作的课程很灵活,您可以毫不费力地使用任何类型。看看下面我的答案,告诉我你的想法:)
                          • 我同意,您的回答肯定比为您要添加到组合框中的每种类型创建派生类更方便。不错的工作!我认为将来如果我没有现成的“名称”之类的属性,我将使用您的答案或字典答案之类的东西:)
                          【解决方案20】:

                          如果只需要最终值作为(字符串),这是一个非常简单的 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 test = testComboBox.SelectedValue.ToString();
                          

                          【讨论】:

                            【解决方案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();
                            

                            【讨论】: