การเชื่อมโยง DataGridView กับ DataTable ด้วย ComboBox ไม่ทำงาน

ฉันกำลังพยายามสร้าง DataGridView ที่ผูกไว้กับ DataTable โดยที่หนึ่งคอลัมน์คือ ComboBox รหัสทำงาน แต่ฉันได้รับข้อผิดพลาดต่อไปนี้หลังจากการผูก (ไม่ใช่เมื่อข้อมูลถูกผูกไว้): System.ArgumentException: ค่า DataGridViewComboBoxCell ไม่ถูกต้อง

ใน DataGridView หนึ่งในคอลัมน์คือ DataGridViewComboBoxColumn ที่ใช้ enum (ชื่อ โครงสร้างประเภท) เป็นแหล่งที่มา:

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

เมื่อฉันเติม DataGridView โดยไม่ใช้ DataTable มันก็ทำงานได้ดี:

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

ตอนนี้ฉันต้องการใช้ DataTable แทน แต่ไม่สามารถใช้งานได้ DataTable ถูกสร้างขึ้นดังนี้:

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

คอลัมน์อื่นๆ ใช้งานได้ดี แต่ฉันไม่สามารถทำให้คอลัมน์ "โครงสร้าง" ทำงานได้ ต่อไปนี้เป็นวิธีที่ฉันพยายามสร้าง Combobox:

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

หลังจากนั้น ฉันแค่สร้างแถวสำหรับตารางและตั้งค่าตารางเป็นแหล่งข้อมูลสำหรับ DataGridView:

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

ฉันได้อ่านโพสต์จำนวนมากที่มีการระบุว่าการใช้ enum ในคอมโบบ็อกซ์ทำให้เกิดปัญหา (ตัวอย่าง: DataGridView เชื่อมโยงกับ DataTable ด้วยคอลัมน์ Combobox ตาม enum) แต่ดูเหมือนจะไม่เป็นเช่นนั้น ฉันยังพยายามใช้อาร์เรย์ของสตริงที่พิมพ์อย่างชัดเจน แต่ยังคงได้รับข้อผิดพลาดเดียวกัน ฉันคิดว่าฉันกำลังทำอะไรผิดกับ DataGridViewComboBoxCell

ปัญหาอาจเกิดจากอะไร?


person JayByte    schedule 31.08.2016    source แหล่งที่มา


คำตอบ (1)


ดูเหมือนว่าขั้นตอนที่คุณขาดหายไปคือการระบุชื่อและค่านิยมสำหรับ CBO DataTable สามารถเก็บค่าได้ และ DGV สามารถแสดงชื่อที่เกี่ยวข้องได้ แต่คุณต้องช่วยจัดเตรียมคำแปล

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

ส่วนแรกจะสร้าง DataTable โปรดทราบว่าประเภทคอลัมน์โครงสร้างคือ structureType (หรือมักจะเป็น int) DataTable จะเก็บข้อมูล ไม่ใช่องค์ประกอบ DataGridViewComboBoxCell ในกรณีที่ข้อมูลมาจากฐานข้อมูล คอลัมน์นั้นจะเป็น int เนื่องจาก structureType ไม่ใช่ประเภทที่รู้จัก

จากนั้น DataSource จะถูกสร้างขึ้นจากชื่อและค่าแจงนับ นี่เป็นวิธีการสำหรับการควบคุมเพื่อแสดงชื่อ แต่เก็บค่าไว้ใน DataTable

หากตั้งค่า DGV ให้สร้างคอลัมน์อัตโนมัติ คุณจะต้องแทนที่ค่าเริ่มต้น TextBoxColumn ด้วย ComboBoxColumn สิ่งนี้กำลังดำเนินการหลังจากตั้งค่า DataSource แล้ว แต่ก่อนที่จะเพิ่มข้อมูลใดๆ เมื่อข้อมูลมาจากฐานข้อมูล (และโดยปกติแล้วจะไม่มีตารางที่พิมพ์ว่าง) คุณสามารถใช้เหตุการณ์ ColumnAdded เพื่อสลับคอลัมน์หนึ่งไปยังอีกคอลัมน์หนึ่งได้

สิ่งสำคัญเมื่อเพิ่มคอลัมน์ CBO คือการตั้งค่าคุณสมบัติ ValueMember และ DsiplayMember เพื่อให้ค่า ‹-> การแปลชื่อ และ DataPropertyName เพื่อให้รู้ว่าจะเก็บค่าที่เลือกไว้ที่ไหนใน DataTable

ป้อนคำอธิบายรูปภาพที่นี่

person Ňɏssa Pøngjǣrdenlarp    schedule 31.08.2016
comment
ขอบคุณ! ฉันหมดความหวังไปแล้ว คำถามเพิ่มเติม: จะมีวิธีง่ายๆ ในการตั้งค่าให้คอมโบบ็อกซ์แสดงว่างหรือไม่ หาก structureType? จะเป็นโมฆะ คงจะเจ๋งดี แต่ฉันสามารถเพิ่มเพียง none ลงใน enum ได้ด้วย - person JayByte; 01.09.2016
comment
การเพิ่ม None จะเป็นวิธีที่ง่ายที่สุด - person Ňɏssa Pøngjǣrdenlarp; 01.09.2016