ComboBox调整项间距

ComboBox调整项间距

 

在一些窗体应用程序中,常常需要重写组合框控件ComboBox的DrawItem事件处理方法,例如:颜色选择组合框、带图标的组合框、调整项间距的组合框,等等。基本步骤如下:

设置ComboBox.DrawMode为OwnerDrawFixed或OwnerDrawVariable;

计算新的下拉框高度值ComboBox.DropDownHeight,或许还要计算宽度ComBoBox.DropDownWidth;

重写ComboBox.DrawItem和ComboBox.MeasureItem等事件处理方法。

下面是两个主要事件的代码举例:

  1. private void comboBox1_DrawItem(object sender, DrawItemEventArgs e)
  2. {
  3.     if (e.Index == -1) { return; } // 未下拉的当前框文本, 不需要重绘制

  4.     ComboBox thisComboBox = sender as ComboBox;  // 当前组合框
  5.     string itemText = Convert.ToString(thisComboBox.Items[e.Index]);  // 由DrawString()处理null情况

  6.     e.DrawBackground();  // 绘制背景
  7.     using (SolidBrush brush = new SolidBrush(e.ForeColor))
  8.     {
  9.         e.Graphics.DrawString(itemText, e.Font, brush, e.Bounds, StringFormat.GenericDefault);  // 绘制文本
  10.     }
  11.     e.DrawFocusRectangle();  // 绘制聚焦框
  12. }

  13. private void comboBox1_MeasureItem(object sender, MeasureItemEventArgs e)
  14. {
  15.     if (e.Index % 2 == 0)
  16.     {
  17.         e.ItemHeight = 15;  // 偶数项的项高
  18.     }
  19.     else
  20.     {
  21.         e.ItemHeight = 25;  // 奇数项的项高
  22.     }
  23. }
复制代码
需要指出如下几点:

如果设置了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属性确定具体的列属性值,获取到待绘制的文本。参考如下代码:
  1. private void comboBox1_DrawItem(object sender, DrawItemEventArgs e)
  2. {
  3.     if (e.Index == -1) { return; }  // 未下拉的当前框文本, 不需要重绘制

  4.     ComboBox thisComboBox = sender as ComboBox;
  5.     DataRowView row = thisComboBox.Items[e.Index] as DataRowView;  // 取序号为e.Index的行对象
  6.     string itemText = Convert.ToString(row[thisComboBox.DisplayMember]);  // 由DrawString()方法处理null
  7.    
  8.     e.DrawBackground();  // 绘制背景
  9.     using (SolidBrush brush = new SolidBrush(e.ForeColor))
  10.     {
  11.         e.Graphics.DrawString(value, e.Font, brush, e.Bounds, StringFormat.GenericDefault);  // 绘制文本
  12.     }
  13.     e.DrawFocusRectangle();  // 绘制聚焦框
  14. }
复制代码
实际应用时注意如下几点:

BindingSource与DataTable.DefaultView属性均实现了IBindingList与IBindingListView接口;

特别地,ComboBox绑定到DataTable,实质上是绑定到DataTable对象的DefaultView属性;

获取的待绘制文本可以是DataRowView的两列或多列的属性值组合,从而绘制出所谓的多列ComboBox。

为便于验证 测试,下面给出一个完整的窗体程序代码:
  1. public partial class Form1 : Form 

  2.     public Form1() 
  3.     { 
  4.         InitializeComponent(); 
  5.     } 
  6.     private void Form1_Load(object sender, EventArgs e) 
  7.     { 
  8.         this.Width = 420; 
  9.         DataTable students = new DataTable(); 
  10.         students.Columns.Add("StudentId", typeof(string)); 
  11.         students.Columns.Add("Name", typeof(string)); 
  12.         students.Columns.Add("Age", typeof(int)); 
  13.         for (int k = 1; k < 30; k++) 
  14.         { 
  15.             DataRow row = students.NewRow(); 
  16.             if (k % 6 != 0) 
  17.             { 
  18.                 row["StudentId"] = "20090129" + k.ToString("00"); 
  19.             } 
  20.             else 
  21.             { 
  22.                 row["StudentId"] = null; 
  23.             } 
  24.             row["Name"] = "StudentName_" + k.ToString("0000"); 
  25.             row["Age"] = 20 + k % 5; 
  26.             students.Rows.Add(row); 
  27.         } 
  28.         students.DefaultView.RowFilter = "Age > 20";  // 过滤一些记录 
  29.         ComboBox comboBox = new ComboBox(); 
  30.         comboBox.Parent = this; 
  31.         comboBox.Location = new Point(10, 10); 
  32.         comboBox.ForeColor = Color.Blue; 
  33.         comboBox.DropDownHeight = comboBox.MaxDropDownItems * 20;  // 下拉后的高度(不含框的高度) 
  34.         comboBox.DrawMode = DrawMode.OwnerDrawVariable;  // 可以由MeasureItem事件设置项高度 
  35.         comboBox.DrawItem += new DrawItemEventHandler(ComboBox_DrawItem); 
  36.         comboBox.MeasureItem += new MeasureItemEventHandler(ComboBox_MeasureItem); 
  37.         comboBox.DisplayMember = "StudentId"; 
  38.         comboBox.DataSource = students; 
  39.         DataGridView dataGridView = new DataGridView(); 
  40.         dataGridView.Parent = this; 
  41.         dataGridView.Location = new Point(10, 40); 
  42.         dataGridView.Width = this.ClientSize.Width - 20; 
  43.         dataGridView.DataSource = students; 
  44.     } 
  45.     private void ComboBox_DrawItem(object sender, DrawItemEventArgs e) 
  46.     { 
  47.         if (e.Index == -1)  // 组合框中的当前项, 不需要重绘 
  48.         { 
  49.             return; 
  50.         } 
  51.         ComboBox thisComboBox = sender as ComboBox; 
  52.         DataRowView row = thisComboBox.Items[e.Index] as DataRowView;  // 取序号为e.Index的项 
  53.         string itemText = Convert.ToString(row[thisComboBox.DisplayMember]);  // 由DrawString()方法处理null 
  54.         e.DrawBackground(); 
  55.         using (SolidBrush brush = new SolidBrush(e.ForeColor)) 
  56.         { 
  57.             e.Graphics.DrawString(itemText, e.Font, brush, e.Bounds, StringFormat.GenericDefault); 
  58.         } 
  59.         e.DrawFocusRectangle(); 
  60.     } 
  61.     private void ComboBox_MeasureItem(object sender, MeasureItemEventArgs e) 
  62.     { 
  63.         e.ItemHeight = 20; 
  64.     } 
  65. }
复制代码

你可能感兴趣的:(ComboBox调整项间距)