[C#]如何讓DataGridView每筆Row呈現不同的Cell Type

[C#]如何讓DataGridView每筆Row呈現不同的Cell Type

DataGridView本身可以設定每個欄位的Type,在新建欄位時就有以下幾種選項可以選擇:

image

 

而設定好Column Type後該欄位便會以該型態的方式做呈現,功能上挺不錯,不過如果我們今天想要得到如下圖的結果時怎麼辦?

image

 

我希望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因為我變動它的型態而被重複觸發了:

image

 

最後我改寫到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會出現下拉選單:

image

 

點選bool會出現CheckBox:

image

 

總算是接近達成了,後來想想應該還有一個方法,那就是跑迴圈讓Row跟Cell是一個一個被加入到DataGridView中的,這樣應該可以做到,不過這段我沒有測試,有空檔再來玩玩吧。

游舒帆 (gipi)

探索原力Co-founder,曾任TutorABC協理與鼎新電腦總監,並曾獲選兩屆微軟最有價值專家 ( MVP ),離開職場後創辦探索原力,致力於協助青少年培養面對未來的能力。認為教育與組織育才其實息息相關,都是在為未來儲備能量,2018年起成立為期一年的專題課程《職涯躍升的關鍵24堂課》,為培養台灣未來的領袖而努力。