繫結資料來源時組合框ComboBox.DrawItem的事件處理方法
阿新 • • 發佈:2019-02-20
在一些窗體應用程式中,常常需要重寫組合框控制元件ComboBox的DrawItem事件處理方法,例如:顏色選擇組合框、帶圖示的組合框、調整項間距的組合框,等等。基本步驟如下:
- 設定ComboBox.DrawMode為OwnerDrawFixed或OwnerDrawVariable;
- 計算新的下拉框高度值ComboBox.DropDownHeight,或許還要計算寬度ComBoBox.DropDownWidth;
- 重寫ComboBox.DrawItem和ComboBox.MeasureItem等事件處理方法。
下面是兩個主要事件的程式碼舉例:
private void comboBox1_DrawItem(object sender, DrawItemEventArgs e) { if (e.Index == -1) { return; } // 未下拉的當前框文字, 不需要重繪製 ComboBox thisComboBox = sender as ComboBox; // 當前組合框 string itemText = Convert.ToString(thisComboBox.Items[e.Index]); // 由DrawString()處理null情況 e.DrawBackground(); // 繪製背景 using (SolidBrush brush = new SolidBrush(e.ForeColor)) { e.Graphics.DrawString(itemText, e.Font, brush, e.Bounds, StringFormat.GenericDefault); // 繪製文字 } e.DrawFocusRectangle(); // 繪製聚焦框 } private void comboBox1_MeasureItem(object sender, MeasureItemEventArgs e) { if (e.Index % 2 == 0) { e.ItemHeight = 15; // 偶數項的項高 } else { e.ItemHeight = 25; // 奇數項的項高 } }
需要指出如下幾點:
- 如果設定了ComboBox.ItemHeight的值,且每個項高度相同,則可以省略事件方法ComboBox.MeasureItem;
- ComboBox.DrawMode為OwnerDrawFixed時,ComboBox.MeasureItem事件失效,此時取ComboBox.ItemHeight的值;
- ComboBox.DrawMode為OwnerDrawVariable時,可以在ComboBox.MeasureItem改變指定項的高度;
- 如果項高固定為height,則下拉框高 ComboBox.DropDownHeight = ComboBox.MaxDropDownItems * height。
當ComboBox繫結到資料來源,且該資料來源實現了IBindingList與IBindingListView介面時(例如:DataTable、BindingSource),ComboBox.Items即是當前的資料來源,通過ComboBox.Items[e.Index]獲取的則是當前資料來源的行物件DataRowView。此時,將根據DataRowView和ComboBox.DisplayMember屬性確定具體的列屬性值,獲取到待繪製的文字。參考如下程式碼:
private void comboBox1_DrawItem(object sender, DrawItemEventArgs e) { if (e.Index == -1) { return; } // 未下拉的當前框文字, 不需要重繪製 ComboBox thisComboBox = sender as ComboBox; DataRowView row = thisComboBox.Items[e.Index] as DataRowView; // 取序號為e.Index的行物件 string itemText = Convert.ToString(row[thisComboBox.DisplayMember]); // 由DrawString()方法處理null e.DrawBackground(); // 繪製背景 using (SolidBrush brush = new SolidBrush(e.ForeColor)) { e.Graphics.DrawString(value, e.Font, brush, e.Bounds, StringFormat.GenericDefault); // 繪製文字 } e.DrawFocusRectangle(); // 繪製聚焦框 }
實際應用時注意如下幾點:
- BindingSource與DataTable.DefaultView屬性均實現了IBindingList與IBindingListView介面;
- 特別地,ComboBox繫結到DataTable,實質上是繫結到DataTable物件的DefaultView屬性;
- 獲取的待繪製文字可以是DataRowView的兩列或多列的屬性值組合,從而繪製出所謂的多列ComboBox。
為便於驗證測試,下面給出一個完整的窗體程式程式碼: