(原创文章·转载请注明来源:http://blog.csdn.net/hulihui)
在一些窗体应用程序中,常常需要重写组合框控件ComboBox的DrawItem事件处理方法,例如:颜色选择组合框、带图标的组合框、调整项间距的组合框,等等。基本步骤如下:
下面是两个主要事件的代码举例:
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绑定到数据源,且该数据源实现了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(); // 绘制聚焦框 }
实际应用时注意如下几点:
补记:本文只非常浅地探讨了DrawItem事件方法,更详细的说明请参考拙文:C#实现的多列数据绑定组合框控件MultiColumnComboBoxEx。
为便于验证测试,下面给出一个完整的窗体程序代码:
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { this.Width = 420; DataTable students = new DataTable(); students.Columns.Add("StudentId", typeof(string)); students.Columns.Add("Name", typeof(string)); students.Columns.Add("Age", typeof(int)); for (int k = 1; k < 30; k++) { DataRow row = students.NewRow(); if (k % 6 != 0) { row["StudentId"] = "20090129" + k.ToString("00"); } else { row["StudentId"] = null; } row["Name"] = "StudentName_" + k.ToString("0000"); row["Age"] = 20 + k % 5; students.Rows.Add(row); } students.DefaultView.RowFilter = "Age > 20"; // 过滤一些记录 ComboBox comboBox = new ComboBox(); comboBox.Parent = this; comboBox.Location = new Point(10, 10); comboBox.ForeColor = Color.Blue; comboBox.DropDownHeight = comboBox.MaxDropDownItems * 20; // 下拉后的高度(不含框的高度) comboBox.DrawMode = DrawMode.OwnerDrawVariable; // 可以由MeasureItem事件设置项高度 comboBox.DrawItem += new DrawItemEventHandler(ComboBox_DrawItem); comboBox.MeasureItem += new MeasureItemEventHandler(ComboBox_MeasureItem); comboBox.DisplayMember = "StudentId"; comboBox.DataSource = students; DataGridView dataGridView = new DataGridView(); dataGridView.Parent = this; dataGridView.Location = new Point(10, 40); dataGridView.Width = this.ClientSize.Width - 20; dataGridView.DataSource = students; } private void ComboBox_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(itemText, e.Font, brush, e.Bounds, StringFormat.GenericDefault); } e.DrawFocusRectangle(); } private void ComboBox_MeasureItem(object sender, MeasureItemEventArgs e) { e.ItemHeight = 20; } }