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


202

Як в C # WinApp можна додати як текст, так і значення до елементів мого ComboBox? Я здійснив пошук, і зазвичай у відповідях використовується "Прив’язання до джерела" .. але в моєму випадку я не маю готового джерела в своїй програмі ... Як я можу зробити щось подібне:

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

Відповіді:


361

Ви повинні створити власний тип класу та замінити метод 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
нам справді потрібен цей новий клас ComboboxItem? Я думаю, що існує вже один, який називається ListItem.
Amr Elgarhy

15
Я вважаю, що це може бути доступне лише в ASP.NET, а не в WinForms.
Адам Марковіц

1
Ні. Елемент - це окремий тип, який використовується лише для зберігання даних елементів (текст, значення, посилання на інші об'єкти тощо). Це не нащадок ComboBox, і це було б надзвичайно рідко.
Адам Марковіц

1
Я знаю, що я дещо запізнююся на вечірку, але, як я це робив у чистому середовищі Windows, було налаштувати таблицю даних, додати до неї елементи та прив’язати комбобокс до даних. Можна було б подумати, що має бути більш чистий спосіб зробити це, але я не знайшов його (DisplayMember - це властивість у комбінаційному вікні, який ви хочете, щоб текст з’явився, ValueMember for Value of data)
user2366842

4
як ми отримуємо "Вибране значення" або вибираємо предмет на основі вартості ... будь ласка, дайте відповідь
Альфа Габріель В. Тимбол

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

2
Працює ідеально, і це має бути обрана відповідь. Але чи не можемо ми використовувати comboBox1.SelectedText замість кастингу .SelectedItem і взяти .Value?
Jeffrey Goines

@fab як ти знайдеш предмет у коробці з певним ключем
Сміт

Чи можливо вибрати елемент у комбінаційному вікні на основі ключа словника? наприклад, виберіть клавішу 3, тому буде вибрано пункт з клавішею 3.
Dror

Цей метод більше не працює для vs2015. Винятки, викинуті на те, що не вдасться прив’язатись до нового показника та Valuemember
Plater

119

Ви можете використовувати анонімний клас на зразок цього:

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;

14
Я хотів би це трохи змінити, оскільки програмісту, певно, знадобиться цикл разом із цим. Замість масиву я використав список. List<Object> items = new List<Object>(); Потім я зміг використати метод items.Add( new { Text = "report A", Value = "reportA" } );у циклі.
Андрій

1
Ендрю, чи отримали Ви список <Object> для роботи з властивістю SelectedValue?
Пітер ПітЛок

@ Венкат,comboBox.SelectedItem.GetType().GetProperty("Value").GetValue(comboBox.SelectedItem, null)
Оптавій

2
@ Venkat, якщо ви використовуєте друге рішення, яке встановлює, DataSourceви можете використовувати SelectedValueабо SelectedTextвластивості комбінованої скриньки , тому не потрібно робити спеціальних кастингу.
JPProgrammer

32

Ви повинні використовувати dynamicоб'єкт для вирішення елемента комбінованої скриньки під час виконання.

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

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

(comboBox.SelectedItem as dynamic).Value

1
Це набагато краще, ніж створення окремого класу та переосмислення ToString ().
Дон Шрот

1
Динамічний доступний лише для C # 4 та новіших версій. (. NET 4.5, я думаю)
MickeyfAgain_BeforeExitOfSO

Просте і швидше писати! Я зробив це для SelectedValue на VB.net: Dim Value As String = CType (Me.SectionIDToComboBox.SelectedItem, Object) .Value
Mambo,

1
Як тоді встановити правильний елемент комбінованого вікна за допомогою "Значення"?
Дейв Людвіг

17

Ви можете використовувати DictionaryObject замість створення спеціального класу для додавання тексту та значення в a Combobox.

Додайте ключі та значення в Dictionaryоб’єкт:

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

Прив’яжіть об'єкт Словник до джерела 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;

Повне джерело: Текст комбобоксу та друге значення


14

Це один із способів, який щойно прийшов до тями:

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 у своїй відповіді .

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


2
Якщо я не помиляюся, ListItem доступний лише в ASP.NET
Адам Марковіц

так :( на жаль, це лише на ASP.net ... так що я можу зробити зараз?
Бон

Тоді в чому полягає сенс властивостей SelectedValue або SelectedText у комбобоні?
JSON

11

Не знаю, чи буде це спрацьовувати ситуація, подана в початковій публікації (не майте на увазі, що це через два роки), але цей приклад працює для мене

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

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

5

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

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тоді вам доведеться відслідковувати тип, який ви використовували для кожного елемента, і вводити його у свій код, щоб правильно його використовувати.

Я використовую його у своїх проектах вже досить давно. Це дуже зручно.


4

Мені сподобалась відповідь 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;

3

Приклад використання 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();

3

Ви можете використовувати цей код, щоб вставити деякі елементи у поле для поєднання з текстом та значенням.

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 індексу. Якщо ви натиснете на поле, з’явиться інший наступний варіант
Мухаммед Ахмед

це не працює для ідентифікаторів, це просто спосіб індексувати список, про це не було питання
пан Хеліс

2

На додаток до відповіді Адама Марковіца, тут є загальний спосіб (відносно) просто встановити 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.


1

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

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

У мене була така ж проблема: те, що я робив, було додати нове 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;
}

0

Створення класу:

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

Ось як це робить 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дзвінки все ще працюють.


0

Це схоже на деякі інші відповіді, але є компактним і уникає перетворення в словник, якщо у вас вже є список.

Дано ComboBox"комбобокс" у формі Windows та клас SomeClassіз stringвластивістю типу Name,

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

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

Що означає, що SelectedItem - це SomeClassоб'єкт list, і кожен елемент в comboboxньому буде відображатися з використанням його імені.


Правда! Я раніше використовував DisplayMember... Я завжди забуваю, що існує. Я звик до рішення, яке я знайшов до того, як звернув увагу на цю властивість, також це не завжди допоможе. Не всі класи мають Nameабо Tagвластивість, або мають рядкове властивість, яке можна використовувати довільно як текст відображення.
Матей Роша

Це хороший момент. Якщо ви можете змінити клас, то, можливо, варто додати таке властивість до класу, наприклад, властивість "ComboBoxText" (яка може повернути метод ToString (), якщо він є). Крім того, якщо клас не піддається зміні, можливо, можливо створити похідний клас, в якому можна було б реалізувати властивість 'ComboBoxText'. Це варто того лише, якщо вам доведеться багато разів додавати клас до ComboBox. В іншому випадку простіше просто використовувати словник, як пояснено в одній з інших відповідей.
Алекс Сміт

Гей, Алекс, я відповів етодом, який зазвичай використовую в цих випадках. Я думаю, що це досить близько до того, що ти сказав, або, можливо, я не зрозумів, що ти сказав. Я не виходив з класу, тому що деякі класи можуть вимагати від вас реалізувати методи, які ми не хочемо переосмислювати (тому у нас буде купа методів з простим base.Method();), також вам доведеться створити похідний клас для кожного іншого типу, який ви хочете додати до комбінованих вікон або списків. Клас, який я зробив, є гнучким, ви можете використовувати будь-який тип без зайвих зусиль. Подивіться моєї відповіді нижче і скажіть, що ви думаєте :)
Матей Роша

Я погоджуюся, ваша відповідь, безумовно, здається зручнішою, ніж створення похідного класу для кожного типу, який ви хочете додати до списку комбінацій. Хороша робота! Я думаю, що в майбутньому, якщо у мене немає такої властивості, як "Ім'я", я легко використаю щось на зразок вашої відповіді чи відповіді зі словника :)
Alex Smith

0

Це дуже просте рішення для форм Windows, якщо все, що потрібно, є кінцевим значенням у вигляді (рядка). Назви предметів будуть відображатися у вікні Combo Box і вибране значення можна легко порівняти.

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

0

Краще рішення тут;

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. Здійснено виклик QueryInterface із запитом інтерфейсу класу COM видимого керованого класу 'ComboBoxUiaProvider
MC9000
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.