[C#]如何讓DataGridView每筆Row呈現不同的Cell Type
DataGridView本身可以設定每個欄位的Type,在新建欄位時就有以下幾種選項可以選擇:
而設定好Column Type後該欄位便會以該型態的方式做呈現,功能上挺不錯,不過如果我們今天想要得到如下圖的結果時怎麼辦?
我希望Value欄位可以依Type欄位來顯示不同的內容,如果是combo的話就要是下拉選單,如果是bool的話就要是CheckBox,方便使用者使用,在Webform的時候我們可能習慣將這樣的程式放在DataBound時,不過Winform的DataGridView沒有這個事件,所以我找了一個很像的事件叫Paint來利用看看:
{
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
DataGridViewRow tNowRow = dataGridView1.Rows[i];
if (tNowRow.Cells["Type"].Value != null)
{
if (tNowRow.Cells["Type"].Value != null)
{
//如果是bool的話就變成CheckBox
if (tNowRow.Cells["Type"].Value.ToString() == "bool")
{
dataGridView1["Value", i] = new DataGridViewCheckBoxCell();
}
//如果是combo的話就變成下拉選單
else if (tNowRow.Cells["Type"].Value.ToString() == "combo")
{
DataGridViewComboBoxCell tCell = new DataGridViewComboBoxCell();
for (int j = 0; j < tNowRow.Cells["AllowedValues"].Value.ToString().Split(';').Length; j++)
{
tCell.Items.Add(tNowRow.Cells["AllowedValues"].Value.ToString().Split(';')[j]);
}
dataGridView1["Value", i] = tCell;
}
}
}
}
}
這個寫法可以達到我所想要的結果,但是寫在Paint中卻會出現Paint事件反覆被觸發,導致程式怎麼跑都跑不完的現象,後來我放棄這個事件,改寫到CellEnter中,退而求其次,改成當使用者點選該欄位時才變換成我想要的元件:
{
//如果是點在Value欄位的話才出現
if (e.ColumnIndex == 1)
{
DataGridViewRow tNowRow = dataGridView1.Rows[dataGridView1.CurrentRow.Index];
if (tNowRow.Cells["Type"].Value != null)
{
if (tNowRow.Cells["Type"].Value != null)
{
//如果是bool的話就變成CheckBox
if (tNowRow.Cells["Type"].Value.ToString() == "bool")
{
dataGridView1["Value", dataGridView1.CurrentRow.Index] = new DataGridViewCheckBoxCell();
}
//如果是combo的話就變成下拉選單
else if (tNowRow.Cells["Type"].Value.ToString() == "combo")
{
DataGridViewComboBoxCell tCell = new DataGridViewComboBoxCell();
for (int i = 0; i < tNowRow.Cells["AllowedValues"].Value.ToString().Split(';').Length; i++)
{
tCell.Items.Add(tNowRow.Cells["AllowedValues"].Value.ToString().Split(';')[i]);
}
dataGridView1["Value", dataGridView1.CurrentRow.Index] = tCell;
}
}
}
}
}
但寫在CellEnter卻會出現這個問題,依訊息看起來的結果也是說某個function因為我變動它的型態而被重複觸發了:
最後我改寫到CellClick中才終於解決我的問題:
{
//如果是點在Value欄位的話才出現
if (e.ColumnIndex == 1)
{
DataGridViewRow tNowRow = dataGridView1.Rows[dataGridView1.CurrentRow.Index];
if (tNowRow.Cells["Type"].Value != null)
{
if (tNowRow.Cells["Type"].Value != null)
{
//如果是bool的話就變成CheckBox
if (tNowRow.Cells["Type"].Value.ToString() == "bool")
{
dataGridView1["Value", dataGridView1.CurrentRow.Index] = new DataGridViewCheckBoxCell();
}
//如果是combo的話就變成下拉選單
else if (tNowRow.Cells["Type"].Value.ToString() == "combo")
{
DataGridViewComboBoxCell tCell = new DataGridViewComboBoxCell();
for (int i = 0; i < tNowRow.Cells["AllowedValues"].Value.ToString().Split(';').Length; i++)
{
tCell.Items.Add(tNowRow.Cells["AllowedValues"].Value.ToString().Split(';')[i]);
}
dataGridView1["Value", dataGridView1.CurrentRow.Index] = tCell;
}
}
}
}
}
點選combo會出現下拉選單:
點選bool會出現CheckBox:
總算是接近達成了,後來想想應該還有一個方法,那就是跑迴圈讓Row跟Cell是一個一個被加入到DataGridView中的,這樣應該可以做到,不過這段我沒有測試,有空檔再來玩玩吧。
游舒帆 (gipi) 探索原力Co-founder,曾任TutorABC協理與鼎新電腦總監,並曾獲選兩屆微軟最有價值專家 ( MVP ),離開職場後創辦探索原力,致力於協助青少年培養面對未來的能力。認為教育與組織育才其實息息相關,都是在為未來儲備能量,2018年起成立為期一年的專題課程《職涯躍升的關鍵24堂課》,為培養台灣未來的領袖而努力。 |