Chinaunix首页 | 论坛 | 博客
  • 博客访问: 86771
  • 博文数量: 56
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 730
  • 用 户 组: 普通用户
  • 注册时间: 2013-08-06 14:50
文章分类
文章存档

2013年(56)

我的朋友

分类: C#/.net

2013-10-09 14:50:17

高考结束了,马上又将会有这么一群孩子,迫不及待的扔下书包,去聚餐,通宵上网,旅行,KTV,闲逛,狂欢……认为自己终于解放了……殊不知,你们离开的,就是天堂。

  -- 致 即将步入社会的孩纸们

  缘由

  最近在维护一个winform项目,公司购买的是DevExpress控件 (请问怎么联系DevExpress工作人员? 我想询问下,广告费是怎么给的。:p),经过公司大牛们对DevExpress控件疯狂的重写、封装、加密、混淆...等一系列的操作,制作了一套 安全+实用 、基于DevExpress控件又高于DevExpress控件的模板。此时,大家也许觉得我夸张了。但是哥很淡定的告诉大家:不信拉倒!

  一系列绚丽的控件中,目前最让我久久不能忘记吃早餐的就是ComboBoxEdit的显示多列的功能。所以我就想,能不能用普通的ComboBox控件实现这样的功能,带着这样的问题询问了没有被公司网络限制的度娘,结果度娘告诉我需要用一个TextBox结合一个ListView或者GridView来实现这样的功能。我嘞个去~ 这不是和Web里面DIV的显示和隐藏一样了么。 搞得跟个二五八萬似的! 深叹一口气,脑子一转想起了上篇《公用章水印工具》中用到的GDI+,于是有了下文:

  实施:新建组件类

  首先,新建一个winform窗体项目,新建一个组件类,并让其继承ComboBox控件类.

  public partial class MyComboBox : ComboBox

  然后,就是需要做的就是:重写涉及到下拉列表显示的事件了。重写之前需要注意到一点是:将ComboBox控件的DrawMode 设置为DrawMode.OwnerDrawVariable(手动绘制元素)

  无废话,直接贴出核心代码:

  ///


  /// 初始化数据源各列的名称 ///

  private void InitializeColumns() { PropertyDescriptorCollection propertyDescriptorCollection = DataManager.GetItemProperties(); columnWidths = new float[propertyDescriptorCollection.Count]; columnNames = new string[propertyDescriptorCollection.Count]; for (int i = 0; i < propertyDescriptorCollection.Count; i++) { string name = propertyDescriptorCollection[i].Name; columnNames[i] = name; } } ///

  /// 显示下拉框的时候出发 ///

  ///

  protected override void OnDropDown(EventArgs e) { base.OnDropDown(e); this.DropDownWidth = (int)CalculateTotalWidth();//计算下拉框的总宽度

  }private float CalculateTotalWidth() { columnPadding = 5; float totalWidth = 0; foreach (int width in columnWidths) { totalWidth += (width + columnPadding); } //总宽度加上垂直滚动条的宽度

  return totalWidth + SystemInformation.VerticalScrollBarWidth; } ///

  /// 获取各列的宽度和项的总宽度 ///

  ///

  protected override void OnMeasureItem(MeasureItemEventArgs e) { base.OnMeasureItem(e); if (DesignMode) { return; } InitializeColumns(); for (int i = 0; i < columnNames.Length; i++) { string item = Convert.ToString(FilterItemOnProperty(Items[e.Index], columnNames[i])); SizeF sizeF = e.Graphics.MeasureString(item, Font);//返回显示项字符串的大小

  columnWidths[i] = Math.Max(columnWidths[i], sizeF.Width); } float totalWidth = CalculateTotalWidth();//计算combobox下拉框项的宽度

  e.ItemWidth = (int)totalWidth;//设置下拉框项的宽度

  } ///

  /// 绘制下拉框的内容 ///

  ///

  protected override void OnDrawItem(DrawItemEventArgs e) { base.OnDrawItem(e); if (DesignMode) { return; } Rectangle boundsRect = e.Bounds;//获取绘制项边界的矩形 //e.DrawBackground();

  e.Graphics.FillRectangle(Brushes.Bisque, e.Bounds); if ((e.State & DrawItemState.Focus) == 0) { //设置鼠标悬浮ComboBox的item的背景色

  e.Graphics.FillRectangle(Brushes.White, e.Bounds); } int lastRight = 0; using (Pen linePen = new Pen(SystemColors.GrayText)) { using (SolidBrush brush = new SolidBrush(ForeColor)) { if (columnNames.Length == 0) {e.Graphics.DrawString(Convert.ToString(Items[e.Index]), Font, brush, boundsRect); } else {//循环各列

  for (int i = 0; i < columnNames.Length; i++){ string item = Convert.ToString(FilterItemOnProperty(Items[e.Index], columnNames[i])); boundsRect.X = lastRight;//列的左边位置

  boundsRect.Width = (int)columnWidths[i] + columnPadding;//列的宽度

  lastRight = boundsRect.Right; //绘制项的内容

  e.Graphics.DrawString(item, Font, brush, boundsRect);//绘制各项间的竖线

  if (i < columnNames.Length - 1) { e.Graphics.DrawLine(linePen, boundsRect.Right, boundsRect.Top, boundsRect.Right, boundsRect.Bottom); }} } } } e.DrawFocusRectangle();}

  上述代码没有什么亮点,稍微了解点GDI+的都能看懂,而且有很丰富的注释。就不一一解释了。

阅读(655) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~