ComboBox: добавление текста и значения к элементу (без источника привязки)

В C# WinApp, как я могу добавить текст и значение для элементов моего ComboBox? Я выполнил поиск, и обычно в ответах используется "Привязка к источнику"... но в моем случае у меня нет готового источника привязки в моей программе... Как я могу сделать что-то вроде этого:

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

21 ответ

Решение

Вы должны создать свой собственный тип класса и переопределить метод 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());
}
// 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;

Вы можете использовать анонимный класс следующим образом:

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

ОБНОВЛЕНИЕ: хотя приведенный выше код будет правильно отображаться в поле со списком, вы не сможете использовать SelectedValue или же SelectedText свойства ComboBox, Чтобы использовать их, свяжите поле со списком, как показано ниже:

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;

Вы должны использовать dynamic объект для разрешения элемента комбинированного списка во время выполнения.

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

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

(comboBox.SelectedItem as dynamic).Value

Ты можешь использовать Dictionary Объект вместо создания пользовательского класса для добавления текста и значения в 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

Это один из способов, который только что пришел в голову:

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 в своем ответе.

Также проверьте эти страницы, они могут помочь:

Не знаю, сработает ли это для ситуации, описанной в оригинальном посте (не говоря уже о том, что это два года спустя), но этот пример работает для меня:

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

Если кому-то все еще интересно это, вот простой и гибкий класс для элемента комбинированного списка с текстом и значением любого типа (очень похоже на пример Адама Марковица):

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

С использованием <T> лучше, чем объявить value как objectпотому что с object Затем вам нужно будет отслеживать тип, который вы использовали для каждого элемента, и использовать его в своем коде, чтобы использовать его правильно.

Я уже давно использую его в своих проектах. Это действительно удобно.

Лучшее решение здесь;

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

Мне понравился ответ 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;

Вы можете использовать этот код combox добавить элемент с текстом и его значением

  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 для combox

Пример использования 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();

Вы можете использовать универсальный тип:

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:

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

В дополнение к ответу Адама Марковица, вот общий способ (относительно) простого 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 обработчик событий, вам нужно установить источник вашего поля со списком, чтобы быть списком ComboEnumItems на основе каждого Enum в вашем Enum тип. Это может быть достигнуто с 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 будет ComboEnumItem а также comboBoxUserReadable.SelectedValue будет EMyEnum,

Класс создания:

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

        }

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

Вот как это делает 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->SelectedItem а также comboBox1->SelectedIndex звонки еще работают.

Это похоже на некоторые другие ответы, но компактно и позволяет избежать преобразования в словарь, если у вас уже есть список.

Учитывая ComboBox "комбобокс" на форме окон и класса SomeClass с string тип собственности Name,

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

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

Это означает, что SelectedItem является SomeClass объект из listи каждый элемент в combobox будет отображаться с использованием его имени.

У меня была такая же проблема, что я сделал, это добавить новый 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;
}

Это очень простое решение для оконных форм, если все, что нужно, это конечное значение в виде (строки). Имена элементов будут отображаться в поле со списком, и выбранное значение можно будет легко сравнить.

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();
Другие вопросы по тегам