Mengikat DataGridView ke DataTable dengan ComboBox tidak berfungsi

Saya mencoba membuat DataGridView yang terikat ke DataTable di mana satu kolomnya adalah ComboBox. Kode berjalan tetapi saya mendapatkan kesalahan berikut setelah mengikat (bukan ketika data terikat): System.ArgumentException: Nilai DataGridViewComboBoxCell tidak valid.

Dalam DataGridView salah satu kolomnya adalah DataGridViewComboBoxColumn yang menggunakan enum (bernama StructureType) sebagai sumbernya:

// ColumnStructure
// 
this.ColumnStructure.ValueType = typeof(structureType);
this.ColumnStructure.DataSource = Enum.GetValues(typeof(structureType));
this.ColumnStructure.HeaderText = "Structure";
this.ColumnStructure.Name = "ColumnStructure";
this.ColumnStructure.DataPropertyName = "Structure";
//

Saat saya mengisi DataGridView tanpa menggunakan DataTable, itu berfungsi dengan baik:

structureType? structure = GetStructure(part);
dgvObjectTypes.Rows.Add(name, type, structure, count);

Sekarang saya ingin menggunakan DataTable, tetapi tidak bisa berfungsi. DataTable dibuat sebagai berikut:

DataTable table = new DataTable();
table.Columns.Add("Name", typeof(string));
table.Columns.Add("Type", typeof(string));
table.Columns.Add("Structure", typeof(DataGridViewComboBoxCell));
table.Columns.Add("Count", typeof(int));

Kolom lain berfungsi dengan baik tetapi saya tidak dapat mengaktifkan kolom "Struktur". Inilah cara saya mencoba membuat kotak kombo:

var cb = new DataGridViewComboBoxCell();
cb.ValueType = typeof(structureType);
cb.DataSource = Enum.GetValues(typeof(structureType));
cb.Value = (structureType)structure;

Setelah itu saya tinggal membuat baris untuk tabel dan mengatur tabel sebagai sumber data untuk DataGridView:

table.Rows.Add(name, type, cb, count);
dgv.DataSource = table;

Saya telah membaca banyak postingan yang menyatakan bahwa menggunakan enum di kotak kombo menyebabkan masalah (misalnya: DataGridView ditautkan ke DataTable dengan kolom Combobox berdasarkan enum), tetapi tampaknya tidak demikian di sini. Saya bahkan mencoba menggunakan array string yang diketik secara eksplisit tetapi masih mendapatkan kesalahan yang sama. Saya rasa saya melakukan sesuatu yang salah dengan DataGridViewComboBoxCell.

Apa masalahnya?


person JayByte    schedule 31.08.2016    source sumber


Jawaban (1)


Sepertinya langkah yang Anda lewatkan adalah memberikan Nama dan Nilai untuk CBO. DataTable dapat menyimpan nilainya, dan DGV dapat menampilkan nama terkait, tetapi Anda perlu membantu menyediakan terjemahannya.

private enum structureType
{ None, Circle, Square, Pyramid}
...

dtStruct = new DataTable();
dtStruct.Columns.Add("Name", typeof(string));
dtStruct.Columns.Add("Type", typeof(string));
dtStruct.Columns.Add("Structure", typeof(structureType));
dtStruct.Columns.Add("Count", typeof(int));

// autogen columns == true
dgv2.DataSource = dtStruct;

// create DataSource as list of Name-Value pairs from enum
var cboSrc = Enum.GetNames(typeof(structureType)).
                    Select( x => new {Name = x, 
                                      Value = (int)Enum.Parse(typeof(structureType),x)
                                      }
                           ).ToList();

// replace auto Text col with CBO col
DataGridViewComboBoxColumn cb = new DataGridViewComboBoxColumn();
cb.ValueType = typeof(structureType);
cb.DataSource = cboSrc;
cb.DisplayMember = "Name";          // important
cb.ValueMember = "Value";           // important
cb.HeaderText = "Structure";
cb.DataPropertyName = "Structure";  // where to store the value

dgv2.Columns.Remove(dgv2.Columns[2]);  // remove txt col
dgv2.Columns.Add(cb);
cb.DisplayIndex = 2;

// add data
dtStruct.Rows.Add("Ziggy", "Foo", structureType.Circle, 6);

Bagian pertama membuat DataTable, perhatikan bahwa tipe kolom Struktur adalah structureType (atau sering kali int). DataTable akan menyimpan data, bukan elemen DataGridViewComboBoxCell. Jika data berasal dari database, kolom tersebut adalah int karena structureType bukanlah tipe yang diketahui.

A DataSource kemudian dibuat dari nama dan nilai enum. Ini menyediakan sarana bagi kontrol untuk menampilkan nama, namun menyimpan nilai di DataTable.

Jika DGV diatur untuk menghasilkan kolom secara otomatis, Anda perlu mengganti TextBoxColumn default dengan ComboBoxColumn. Ini dilakukan setelah DataSource disetel, tetapi sebelum data apa pun ditambahkan. Ketika data berasal dari DB (sehingga biasanya tidak ada tabel kosong yang diketik), Anda dapat menggunakan acara ColumnAdded untuk menukar satu kolom dengan kolom lainnya.

Hal penting saat menambahkan kolom CBO adalah mengatur properti ValueMember dan DsiplayMember untuk memberikan terjemahan Nilai ‹-> Nama dan DataPropertyName sehingga mengetahui di mana menyimpan nilai yang dipilih di DataTable.

masukkan deskripsi gambar di sini

person Ňɏssa Pøngjǣrdenlarp    schedule 31.08.2016
comment
Terima kasih! Saya sudah kehilangan harapan. Pertanyaan lebih lanjut: Apakah ada cara mudah untuk mengatur tampilan kotak kombo menjadi kosong jika structureType? menjadi nol? Ini akan keren, tapi saya juga bisa menambahkan None ke enum. - person JayByte; 01.09.2016
comment
Menambahkan None akan menjadi yang paling sederhana. - person Ňɏssa Pøngjǣrdenlarp; 01.09.2016