ComboBox: Menambahkan Teks dan Nilai ke Item (tanpa Sumber Binding)

202

Di C # WinApp, bagaimana saya bisa menambahkan Teks dan Nilai ke item ComboBox saya? Saya melakukan pencarian dan biasanya jawabannya menggunakan "Binding ke sumber" .. tetapi dalam kasus saya saya tidak memiliki sumber yang mengikat siap dalam program saya ... Bagaimana saya bisa melakukan sesuatu seperti ini:

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

Jawaban:

361

Anda harus membuat tipe kelas Anda sendiri dan mengganti metode ToString () untuk mengembalikan teks yang Anda inginkan. Ini adalah contoh sederhana dari kelas yang dapat Anda gunakan:

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

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

Berikut ini adalah contoh sederhana penggunaannya:

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());
}
Adam Markowitz
sumber
4
apakah kita benar-benar membutuhkan ComboboxItem kelas baru ini? Saya pikir sudah ada yang disebut ListItem.
Amr Elgarhy
15
Saya percaya bahwa mungkin hanya tersedia di ASP.NET dan bukan WinForms.
Adam Markowitz
1
Tidak. Item adalah tipe terpisah yang hanya digunakan untuk menyimpan data item (teks, nilai, referensi ke objek lain, dll). Ini bukan turunan dari ComboBox dan itu akan sangat jarang terjadi.
Adam Markowitz
1
Saya tahu saya agak terlambat ke pesta, tetapi bagaimana saya melakukan ini di lingkungan bentuk windows murni adalah untuk membuat data, menambahkan item ke dalamnya, dan mengikat kotak kombo ke datatable. Orang akan berpikir bahwa harus ada cara yang lebih bersih untuk melakukannya, tetapi saya belum menemukan satu (DisplayMember adalah properti di kotak kombo yang Anda inginkan untuk menampilkan teks, ValueMember untuk Nilai data)
user2366842
4
bagaimana kita mendapatkan "SelectedValue" atau pilih item berdasarkan nilai ... harap balas
Alpha Gabriel V. Timbol
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;
hebat
sumber
2
Berfungsi sempurna dan ini harus menjadi jawaban yang dipilih. Tapi tidak bisakah kita menggunakan comboBox1.SelectedText daripada casting .SelectedItem dan ambil .Value?
Jeffrey Goines
@ fab bagaimana Anda menemukan item dalam kotak kombo dengan kunci tertentu
Smith
Apakah mungkin untuk memilih item dalam kotak kombo berdasarkan Kunci Kamus? seperti pilih Key 3 sehingga Item dengan Key 3 akan dipilih.
Dror
Metode ini tidak lagi berfungsi untuk vs2015. Pengecualian yang dilontarkan tentang tidak dapat mengikat ke displaymember dan Valuemember baru
Plater
119

Anda dapat menggunakan kelas anonim seperti ini:

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

UPDATE: Meskipun kode di atas akan ditampilkan dengan benar di kotak kombo, Anda tidak akan dapat menggunakan SelectedValueatau SelectedTextproperti dari ComboBox. Untuk dapat menggunakannya, ikat kotak kombo seperti di bawah ini:

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;
buhtla
sumber
14
Saya ingin sedikit memodifikasi ini karena seorang programmer cenderung memerlukan for for loop bersama dengan ini. Alih-alih array saya menggunakan daftar List<Object> items = new List<Object>(); Kemudian saya bisa menggunakan metode items.Add( new { Text = "report A", Value = "reportA" } );dalam loop.
Andrew
1
Andrew, apakah Anda membuat Daftar <Object> berfungsi dengan properti SelectedValue?
Peter PitLock
@Venkat,comboBox.SelectedItem.GetType().GetProperty("Value").GetValue(comboBox.SelectedItem, null)
Optavius
2
@Venkat jika Anda menggunakan solusi kedua yang mengatur DataSourceAnda dapat menggunakan SelectedValueatau SelectedTextproperti kotak kombo, jadi tidak perlu melakukan casting khusus.
JPProgrammer
32

Anda harus menggunakan dynamicobjek untuk menyelesaikan item kotak kombo dalam waktu berjalan.

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

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

(comboBox.SelectedItem as dynamic).Value
Mert Cingoz
sumber
1
Ini jauh lebih baik daripada membuat kelas yang terpisah dan mengesampingkan ToString ().
Don Shrout
1
dinamis hanya tersedia dalam C # 4 dan lebih tinggi. (.NET 4.5 Saya pikir)
MickeyfAgain_BeforeExitOfSO
Sederhana dan lebih cepat untuk menulis! Saya melakukan ini untuk SelectedValue di VB.net: Nilai Dim Sebagai String = CType (Me.SectionIDToComboBox.SelectedItem, Object) .Value
Hannington Mambo
1
Lalu bagaimana, untuk mengatur item kotak kombo yang benar menggunakan "Nilai"?
Dave Ludwig
17

Anda bisa menggunakan DictionaryObject alih-alih membuat kelas khusus untuk menambahkan teks dan nilai dalam a Combobox.

Tambahkan kunci dan nilai dalam DictionaryObjek:

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

Bind objek Kamus sumber ke Combobox:

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

Ambil Kunci dan nilai:

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

Sumber Lengkap: Teks Combobox dan Nilai

kroninaval
sumber
14

Ini adalah salah satu cara yang baru saja terpikir:

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

Dan untuk mengubah teks atau nilai suatu barang, Anda dapat melakukannya seperti ini:

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

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

Tidak ada kelas yang disebut ListItem di Windows Forms . Itu hanya ada di ASP.NET , jadi Anda harus menulis kelas Anda sendiri sebelum menggunakannya, sama seperti yang dilakukan @Adam Markowitz dalam jawabannya .

Periksa juga halaman-halaman ini, mereka dapat membantu:

Amr Elgarhy
sumber
2
Kecuali saya salah, ListItem hanya tersedia di ASP.NET
Adam Markowitz
ya :( sayangnya hanya ada di ASP.net ... jadi apa yang bisa saya lakukan sekarang?
Bohn
Lalu apa gunanya properti SelectedValue atau SelectedText dalam kotak kombo?
JSON
11

Tidak tahu apakah ini akan berfungsi untuk situasi yang diberikan di pos asli (apalagi fakta bahwa ini adalah dua tahun kemudian), tetapi contoh ini cocok untuk saya:

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

Untuk membaca kembali nilai Anda, Anda harus membuang properti SelectedItem ke objek DictionaryEntry, dan Anda kemudian bisa mengevaluasi properti Key dan Value dari itu. Misalnya:

DictionaryEntry deImgType = (DictionaryEntry)cmbImageType.SelectedItem;
MessageBox.Show(deImgType.Key + ": " + deImgType.Value);
ChuckG
sumber
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);
Ryan
sumber
5

Jika ada yang masih tertarik dengan hal ini, berikut adalah kelas sederhana dan fleksibel untuk item combobox dengan teks dan nilai jenis apa pun (sangat mirip dengan contoh 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;
    }
}

Menggunakan <T>lebih baik daripada mendeklarasikan valuesebagai object, karena dengan itu objectAnda harus melacak jenis yang Anda gunakan untuk setiap item, dan memasukkannya ke dalam kode Anda untuk menggunakannya dengan benar.

Saya sudah menggunakannya pada proyek saya untuk sementara waktu sekarang. Ini sangat berguna.

Matheus Rocha
sumber
4

Saya menyukai jawaban fab tetapi tidak ingin menggunakan kamus untuk situasi saya jadi saya mengganti daftar tuple.

// 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;
Maggie
sumber
3

Contoh menggunakan 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();
Soenhay
sumber
3

Anda dapat menggunakan kode ini untuk memasukkan beberapa item ke dalam kotak kombo dengan teks dan nilai.

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"/>
Muhammad Ahmad
sumber
Tolong jelaskan solusi Anda.
Vaibhav Bajaj
Sederhananya, tambahkan negara-negara berikut dalam indeks masing-masing dalam sebuah combox. Ketika Anda menjalankannya. Sebuah combox muncul dengan opsi yang pada 0 index.If Anda mengklik combox pilihan berikut lainnya akan menunjukkan
Muhammad Ahmad
ini tidak bekerja untuk id. Ini hanya cara untuk mengindeks daftar, bukan itu pertanyaannya
Mr Heelis
2

Lebih jauh dari jawaban Adam Markowitz, berikut ini adalah cara tujuan umum (relatif) hanya mengatur ItemSourcenilai - nilai kotak kombo menjadi enums, sambil menunjukkan atribut 'Deskripsi' kepada pengguna. (Anda akan berpikir semua orang ingin melakukan ini sehingga itu akan menjadi .NET one liner, tetapi tidak, dan ini adalah cara paling elegan yang saya temukan).

Pertama, buat kelas sederhana ini untuk mengonversi nilai Enum apa pun menjadi item 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;
    }
}

Kedua di OnLoadevent handler Anda, Anda perlu mengatur sumber dari kotak kombo Anda menjadi daftar ComboEnumItemsberdasarkan setiap tipe EnumAnda Enum. Ini bisa dicapai dengan Linq. Kemudian cukup atur 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";
    }

Sekarang pengguna akan memilih dari daftar ramah pengguna Anda Descriptions, tetapi apa yang mereka pilih akan menjadi enumnilai yang dapat Anda gunakan dalam kode. Untuk mengakses pilihan pengguna dalam kode, comboBoxUserReadable.SelectedItemakan menjadi ComboEnumItemdan comboBoxUserReadable.SelectedValueakan menjadi EMyEnum.

Bill Pascoe
sumber
1

Anda dapat menggunakan Jenis generik:

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

Contoh menggunakan int-Type sederhana:

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);
    }
Jan Staecker
sumber
0

Saya memiliki masalah yang sama, apa yang saya lakukan adalah menambahkan yang baru ComboBox dengan nilai dalam indeks yang sama kemudian yang pertama, dan kemudian ketika saya mengubah pokok kombo indeks dalam perubahan kedua pada waktu yang sama, maka saya mengambil nilainya dari kombo kedua dan menggunakannya.

Ini kodenya:

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;
}
Miguel
sumber
0

Pembuat kelas:

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

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

        }

    }
}
Isa tanpa batas
sumber
0

Beginilah Visual Studio 2013 melakukannya:

Item tunggal:

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

Beberapa item:

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

Tidak perlu melakukan override kelas atau memasukkan hal lain. Dan ya itu comboBox1->SelectedItemdan comboBox1->SelectedIndexpanggilan masih bekerja.

Enigma
sumber
0

Ini mirip dengan beberapa jawaban lain, tetapi ringkas dan menghindari konversi ke kamus jika Anda sudah memiliki daftar.

Diberi ComboBox"combobox" pada formulir windows dan kelas SomeClassdengan stringtipe properti Name,

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

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

Yang berarti SelectedItem adalah SomeClassobjek dari list, dan setiap item comboboxakan ditampilkan menggunakan namanya.

Alex Smith
sumber
Benar! Saya telah menggunakan DisplayMembersebelumnya ... Saya selalu lupa itu ada. Saya terbiasa dengan solusi yang saya temukan sebelum saya memperhatikan properti ini, juga itu tidak selalu membantu. Tidak semua kelas memiliki Nameatau Tagproperti, atau memiliki properti string yang dapat digunakan secara sewenang-wenang sebagai teks tampilan.
Matheus Rocha
Ini poin yang bagus. Jika Anda dapat memodifikasi kelas maka mungkin layak untuk menambahkan properti seperti itu ke kelas, misalnya properti 'ComboBoxText' (yang dapat mengembalikan metode ToString () jika tersedia). Sebagai alternatif, jika kelas tidak dapat dimodifikasi, dimungkinkan untuk membuat kelas turunan di mana properti 'ComboBoxText' dapat diimplementasikan. Ini hanya akan bernilai jika Anda harus menambahkan kelas ke ComboBox berkali-kali. Jika tidak, lebih mudah menggunakan kamus seperti yang dijelaskan dalam salah satu jawaban lain.
Alex Smith
Hei Alex, saya telah membuat jawaban dengan ethod yang biasanya saya gunakan dalam kasus ini. Saya pikir itu cukup dekat dengan apa yang Anda katakan atau mungkin saya tidak mengerti apa yang Anda katakan. Saya tidak berasal dari kelas karena beberapa kelas mungkin mengharuskan Anda untuk mengimplementasikan metode yang tidak ingin kami timpa (jadi kami akan memiliki banyak metode dengan sederhana base.Method();), Anda juga harus membuat kelas turunan untuk setiap jenis berbeda yang ingin Anda tambahkan ke kotak kombo atau kotak daftar. Kelas yang saya buat fleksibel, dapat digunakan dengan jenis apa pun tanpa usaha ekstra. Lihat di bawah untuk jawaban saya, dan katakan apa yang Anda pikirkan :)
Matheus Rocha
Saya setuju, jawaban Anda tampaknya lebih nyaman daripada membuat kelas turunan untuk setiap jenis yang ingin Anda tambahkan ke kotak kombo. Pekerjaan yang baik! Saya pikir di masa depan jika saya tidak memiliki properti seperti 'Nama' tersedia saya akan menggunakan sesuatu seperti jawaban Anda atau jawaban kamus :)
Alex Smith
0

Ini adalah solusi yang sangat sederhana untuk bentuk windows jika semua yang dibutuhkan adalah nilai akhir sebagai (string). Nama-nama item akan ditampilkan di Combo Box dan nilai yang dipilih dapat dengan mudah dibandingkan.

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;

dan pada event handler mendapatkan nilai (string) dari nilai yang dipilih

string test = testComboBox.SelectedValue.ToString();
Esteban Verbel
sumber
0

Solusi yang lebih baik di sini;

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

Retreive Data

MessageBox.Show(cmbUser.SelectedValue.ToString());
Orhan Bayram
sumber
Sementara saya dapat mengisi kotak kombo, mengkliknya menghasilkan kesalahan ini di VS2019 Panggilan QueryInterface dibuat meminta antarmuka kelas COM kelas dikelola terlihat 'ComboBoxUiaProvider
MC9000