C#实现的多列数据绑定组合框控件MultiColumnComboBoxEx
2009-02-01 14:37
696 查看
(原创文章,转载请注明来源:http://blog.csdn.net/hulihui)
![](http://p.blog.csdn.net/images/p_blog_csdn_net/hulihui/EntryImages/20090201/MultiColumnComboBoxEx633690961602046250.gif)
不能分别设置框高与项高,在调整项高ItemHeigth时也调整了组合框本身的高度;
绑定数据源时,只有DisplayMember与ValueMember两个属性,不能呈现多列信息。
在著名开源网CodeProject上找了年份较新的两篇文章:A data-bound multi-column combobox(Nishant Sivakumar, 2007.7)介绍的数据源绑定控件MultiColumnComboBox基本满足要求,但不能独立设置框高和项高;Searchable MultiColumn ComboBox with Linked TextBox(Darryl Caillouet,2008.2) 介绍的同名控件功能强大,也没有分开框高与项高,且不能指定多列的呈现顺序。于是,借鉴这两个开源倥件的主要技术与思路,在增补与完善部分功能后编写出MultiColumnComboBoxEx控件,主要功能如下:
多数据列显示:可以在下拉框和文本框中显示多列信息;
指定列与顺序:可以指定需要显示的数据源列名,同时指定输出顺序;
框高项高分离:可以分别设定文本框本身高度与下拉框的项高度;
查找函数ItemIndexOf:提供了代替Items.Index的数据项查找函数ItemIndexOf;
RTL语言风格:支持一些国家或民族的RightToLeft(RTL)语言风格。
此外,还增补与完善了一些实现细节,例如:是否显示分隔线、是否在框中显示多列、下拉框文本垂直居中、获取全部显示列文本框、DropDownWidth/DropDownHeight计算、RTL时增加左边宽度,等等。
ComboBoxHeight:组合框高度,该属性取代了基类的ItemHeight,项高属性则由ItemDropDownHeight代替;
DisplayColumnNames:数据源绑定时,可以指定下拉框呈现的列名及顺序,列名之间用逗号(,)或|分隔,不区分大小写,列名之间可以有空格。例如,Employee Id,Name,Job,或employee id|name,job。该属性为空时表示全部的列并按数据源的列顺序,列名错误时该列名无效;
DisplayMultiColumnsInBox:为true时在文本框中显示多列信息;
DisplayVerticalLine:为true时在下拉框中显示分隔线;
DrawMode:基类的new属性,只能设置为DrawMode.OwnerDrawVariable;
DropDownStyle:基类的new属性,只能是DropDown与DropDownList;
ItemDropDownHeight:下拉框项的高度,代替基类的ItemHeight属性;
MaxDropDownItems:基类的new属性,用于重算下拉框高度;
TextDisplayed:多列显示时获取用逗号(,)分隔的显示文本;
Version:控件版本。
需要指出,上述new属性是指类定义中重写基类的某个属性并附加关键字new,如下代码给出了DrawMode的new属性:
上述new属性继承了基类的全部Attribute,如:默认值(DefaultValue)、说明(Description)、分类(Category),等等。
控件MultiColumnComboBoxEx提供了一个有4个重载版本的项查找public方法ItemIndexOf,用来取代Items.IndexOf,其函数原型如下:
public int ItemIndexOf(string itemValue, bool ignoreCase, string columnName)
public int ItemIndexOf(string itemValue, string columnName)
public int ItemIndexOf(string itemValue, bool ignoreCase)
public int ItemIndexOf(string itemValue)
函数返回第一个查找到的项的索引号,-1表示指定列没有要查找的值。函数的各个参数用途如下:
itemValue:要查找指定列的项值,省略columnName时表示查找控件DisplayMember属性指定的列;
ignoreCase:是否忽略大小写,默认true,即不区分大小写;
columnName:要查找的列名称,默认是控件属性DisplayMember给出的列。
计算DropDownHeight公式:base.DropDownHeight = base.MaxDropDownItems * m_itemDropDownHeight + m_bottomOffset。其中,固定偏移量m_bottomOffset = 2(无技术资料,俺猜出来的,呵呵。);
相关属性更新时重算高度:更新三种属性时需要调用私有函数SetDropDownHeight(),该函数重算高度并调用函数base.RefreshItems():更新了ItemDrowpDownHeight、ComboBoxHeight与MaxDropDownItems属性值。其中,base.RefreshItems()函数将刷新组合框的所有项,激发事件OnMeasureItem并计算每列的输出宽度。
上述代码中,m_columnNames是列名集合Collection<string>,存储指定的列名,并按先后顺序输出各列。m_maxItemWidth是无数据源时项的最大宽度,m_columnWidths[]数组表示每列的最大宽度。this.DropDownTotalWidht属性表示下拉框总宽度。
特别需要指出,只有调用base.RefreshItems()函数,才能在修改相关属性时激发MeasureItem事件,归纳起来有如下属性更改时需要重算项宽度与列宽度:
DisplayColumnNames:更新了显示列或顺序
DataSource:更新绑定的数据源
ComboBoxHeight:更新组合框高度
ItemDropDownHeight:更新下拉框项的高度
MaxDropDownItems:更新最大下拉项数
还需要指出,增加数据项(增加数据源的数据项、无数据源时增加Items项)时,将自动激发MeasureItem事件,重算各个宽度值。
寒假过去两周了,期间发布了基于WebService的自升级框架WebSAUF 1.0:一个ClickOnce的替代方案 1.0,写篇了现在看起来十分肤浅的文章:绑定数据源时组合框ComBoBox.DrawItem的事件处理方法。因项目应用中感觉ComboBox不够灵活,于是在已有控件基础上改写为MultiColumnComboBoxEx。现在,得抓紧时间做交通统计综合历史数据库项目(HNJT-ISHDB)了,否则无法交差哦!uggah-muggah!
附注:关于项为空(即Items.Count=0)的bug处理和框高项高的设置方法,请参考拙文MultiColumnComboBoxEx: An Extended Data-Bound Multiple Column ComboBox。
MultiColumnComboBoxEx 1.0(C#2005), 2009年2月1日。
![](http://p.blog.csdn.net/images/p_blog_csdn_net/hulihui/EntryImages/20081011/download.gif)
下载V1.0源码与示例。
MultiColumnComboBoxEx 1.1(C#2005), 2009年2月10日。
![](http://p.blog.csdn.net/images/p_blog_csdn_net/hulihui/EntryImages/20081011/download.gif)
下载V1.1(更新)源码与示例。
MultiColumnComboBoxEx 1.2(C#2005), 2009年2月18日。
![](http://p.blog.csdn.net/images/p_blog_csdn_net/hulihui/EntryImages/20081011/download.gif)
下载V1.2源码与示例。
修改了焦点问题:点击另一个MultiColumnComboBoxEx的下拉图标时,该控件没有聚焦。
精细了RTL对齐:在RTL风格时,精确了左边对齐。
![](http://p.blog.csdn.net/images/p_blog_csdn_net/hulihui/EntryImages/20090201/MultiColumnComboBoxEx633690961602046250.gif)
0、前言
组合框ComboBox是一个十分常用的多功能窗体控件,兼具文本框(TextBox)与列表框(ListBox)两控件的特点,并独具特性AutoCompleteMode。但笔者在实际项目开发中往往感到如下方面的不足:不能分别设置框高与项高,在调整项高ItemHeigth时也调整了组合框本身的高度;
绑定数据源时,只有DisplayMember与ValueMember两个属性,不能呈现多列信息。
在著名开源网CodeProject上找了年份较新的两篇文章:A data-bound multi-column combobox(Nishant Sivakumar, 2007.7)介绍的数据源绑定控件MultiColumnComboBox基本满足要求,但不能独立设置框高和项高;Searchable MultiColumn ComboBox with Linked TextBox(Darryl Caillouet,2008.2) 介绍的同名控件功能强大,也没有分开框高与项高,且不能指定多列的呈现顺序。于是,借鉴这两个开源倥件的主要技术与思路,在增补与完善部分功能后编写出MultiColumnComboBoxEx控件,主要功能如下:
多数据列显示:可以在下拉框和文本框中显示多列信息;
指定列与顺序:可以指定需要显示的数据源列名,同时指定输出顺序;
框高项高分离:可以分别设定文本框本身高度与下拉框的项高度;
查找函数ItemIndexOf:提供了代替Items.Index的数据项查找函数ItemIndexOf;
RTL语言风格:支持一些国家或民族的RightToLeft(RTL)语言风格。
此外,还增补与完善了一些实现细节,例如:是否显示分隔线、是否在框中显示多列、下拉框文本垂直居中、获取全部显示列文本框、DropDownWidth/DropDownHeight计算、RTL时增加左边宽度,等等。
1、MultiColumnComboBoxEx介绍
该控件派生自ComboBox,下面介绍其增加与重载(new)的一些属性、功能和及使用:ComboBoxHeight:组合框高度,该属性取代了基类的ItemHeight,项高属性则由ItemDropDownHeight代替;
DisplayColumnNames:数据源绑定时,可以指定下拉框呈现的列名及顺序,列名之间用逗号(,)或|分隔,不区分大小写,列名之间可以有空格。例如,Employee Id,Name,Job,或employee id|name,job。该属性为空时表示全部的列并按数据源的列顺序,列名错误时该列名无效;
DisplayMultiColumnsInBox:为true时在文本框中显示多列信息;
DisplayVerticalLine:为true时在下拉框中显示分隔线;
DrawMode:基类的new属性,只能设置为DrawMode.OwnerDrawVariable;
DropDownStyle:基类的new属性,只能是DropDown与DropDownList;
ItemDropDownHeight:下拉框项的高度,代替基类的ItemHeight属性;
MaxDropDownItems:基类的new属性,用于重算下拉框高度;
TextDisplayed:多列显示时获取用逗号(,)分隔的显示文本;
Version:控件版本。
需要指出,上述new属性是指类定义中重写基类的某个属性并附加关键字new,如下代码给出了DrawMode的new属性:
public new DrawMode DrawMode { get { return base.DrawMode; } set { if (value != DrawMode.OwnerDrawVariable) { throw new NotSupportedException("Must be DrawMode.OwnerDrawVariable"); } base.DrawMode = value; } }
上述new属性继承了基类的全部Attribute,如:默认值(DefaultValue)、说明(Description)、分类(Category),等等。
控件MultiColumnComboBoxEx提供了一个有4个重载版本的项查找public方法ItemIndexOf,用来取代Items.IndexOf,其函数原型如下:
public int ItemIndexOf(string itemValue, bool ignoreCase, string columnName)
public int ItemIndexOf(string itemValue, string columnName)
public int ItemIndexOf(string itemValue, bool ignoreCase)
public int ItemIndexOf(string itemValue)
函数返回第一个查找到的项的索引号,-1表示指定列没有要查找的值。函数的各个参数用途如下:
itemValue:要查找指定列的项值,省略columnName时表示查找控件DisplayMember属性指定的列;
ignoreCase:是否忽略大小写,默认true,即不区分大小写;
columnName:要查找的列名称,默认是控件属性DisplayMember给出的列。
2、实现技术要点
定制多列组合框控件关键步骤包括:1)设置DrawMode为DrawMode.OwnerDrawFixed或DrawMode.OwnerDrawVariable;2)重写OnDrawItem与OnMeasureItem方法,相关技术要点请参考文章A data-bound multi-column combobox与Searchable MultiColumn ComboBox with Linked TextBox。这里介绍控件MultiColumnComBoBoxEx与它们的不同点,主要体现在:下拉框高度与宽度计算、文本框中显示多列。2.1 下拉框高度DropDownHeight计算
由于弃用基类属性ItemHeight,使用自定义的ItemDropDownHeight,此时需要考虑下拉框高度计算问题:计算DropDownHeight公式:base.DropDownHeight = base.MaxDropDownItems * m_itemDropDownHeight + m_bottomOffset。其中,固定偏移量m_bottomOffset = 2(无技术资料,俺猜出来的,呵呵。);
相关属性更新时重算高度:更新三种属性时需要调用私有函数SetDropDownHeight(),该函数重算高度并调用函数base.RefreshItems():更新了ItemDrowpDownHeight、ComboBoxHeight与MaxDropDownItems属性值。其中,base.RefreshItems()函数将刷新组合框的所有项,激发事件OnMeasureItem并计算每列的输出宽度。
2.2 下拉框宽度DropDownWidth计算
在有无数据源绑定时,下拉框宽度计算公式不同,在方法OnMeasureItem中计算下拉框与每个项宽度,代码如下:protected override void OnMeasureItem(MeasureItemEventArgs e) { base.OnMeasureItem(e); if (m_columnNames.Count == 0) // 无绑定数据源 { string item = Convert.ToString(Items[e.Index]) + "A"; // 增加一个字母 int width = (int)(e.Graphics.MeasureString(item, base.Font).Width); if (width > m_maxItemWidth) { m_maxItemWidth = width; // 项的最大宽度 } } else { for (int k = 0; k < m_columnNames.Count; k++) // 计算每个列的最大宽度 { string item = Convert.ToString(FilterItemOnProperty(Items[e.Index], m_columnNames[k])); int width = (int)(e.Graphics.MeasureString(item, base.Font).Width + m_columnPadding + m_leftOffset); m_columnWidths[k] = Math.Max(m_columnWidths[k], width); } } e.ItemWidth = this.DropDownTotalWidth; e.ItemHeight = m_itemDropDownHeight; }
上述代码中,m_columnNames是列名集合Collection<string>,存储指定的列名,并按先后顺序输出各列。m_maxItemWidth是无数据源时项的最大宽度,m_columnWidths[]数组表示每列的最大宽度。this.DropDownTotalWidht属性表示下拉框总宽度。
特别需要指出,只有调用base.RefreshItems()函数,才能在修改相关属性时激发MeasureItem事件,归纳起来有如下属性更改时需要重算项宽度与列宽度:
DisplayColumnNames:更新了显示列或顺序
DataSource:更新绑定的数据源
ComboBoxHeight:更新组合框高度
ItemDropDownHeight:更新下拉框项的高度
MaxDropDownItems:更新最大下拉项数
还需要指出,增加数据项(增加数据源的数据项、无数据源时增加Items项)时,将自动激发MeasureItem事件,重算各个宽度值。
2.3 在文本框中显示多列
在DropDownStyle.DropDownList时,可以在文本框中显示多列信息,此时需要在OnDrawItem方法判断是否绘制当前的文本框,方法是:判断事件参数e.State是否具有DrawItemState.ComboBoxEdit位,即(e.State & DrawItemState.ComboBoxEdit) != 0 表示正在绘制文本框。3、总结、版本与源码
实现了下拉框中显示多列信息,但在文本框中绘制多列信息仅仅针对DropDownStyle.DropDownList风格,DropDownStyle.DropDown时无效。笔者没有找到直接捕获ComboBox的文本框绘制事件。虽然通过OnFormat可以定制输出格式(FormattingEnabled为false该事件无效),但不能Paint/Draw输出文本。另外,也没有考虑组合框的另一个强大功能AutoCompleteMode(可以参考文章Searchable MultiColumn ComboBox with Linked TextBox及其源码)。欢迎使用、评论与建议MultiColumnComboBoxEx。寒假过去两周了,期间发布了基于WebService的自升级框架WebSAUF 1.0:一个ClickOnce的替代方案 1.0,写篇了现在看起来十分肤浅的文章:绑定数据源时组合框ComBoBox.DrawItem的事件处理方法。因项目应用中感觉ComboBox不够灵活,于是在已有控件基础上改写为MultiColumnComboBoxEx。现在,得抓紧时间做交通统计综合历史数据库项目(HNJT-ISHDB)了,否则无法交差哦!uggah-muggah!
附注:关于项为空(即Items.Count=0)的bug处理和框高项高的设置方法,请参考拙文MultiColumnComboBoxEx: An Extended Data-Bound Multiple Column ComboBox。
MultiColumnComboBoxEx 1.0(C#2005), 2009年2月1日。
![](http://p.blog.csdn.net/images/p_blog_csdn_net/hulihui/EntryImages/20081011/download.gif)
下载V1.0源码与示例。
MultiColumnComboBoxEx 1.1(C#2005), 2009年2月10日。
![](http://p.blog.csdn.net/images/p_blog_csdn_net/hulihui/EntryImages/20081011/download.gif)
下载V1.1(更新)源码与示例。
MultiColumnComboBoxEx 1.2(C#2005), 2009年2月18日。
![](http://p.blog.csdn.net/images/p_blog_csdn_net/hulihui/EntryImages/20081011/download.gif)
下载V1.2源码与示例。
修改了焦点问题:点击另一个MultiColumnComboBoxEx的下拉图标时,该控件没有聚焦。
精细了RTL对齐:在RTL风格时,精确了左边对齐。
相关文章推荐
- 11_C# 实现VMS客户端——控件_ComboBoxEx
- C# 程序中如何向(DEV)ComboBoxEdit控件中添加下拉列表的值不使用数据绑定,就是使用代码添加
- C#中为啥俺地ComboBox控件在数据绑定时加载速度很慢
- 如何使数据绑定的控件实现“上一条”、“下一条”、“第一条”和“最后一条”的功能?(WinForm, C#)
- C# 将Dictionary,StringDictionary等集合数据绑定到如comboBox等控件数据源中将获取健值
- C#中ComboBox控件绑定数据源
- C#实现WinForm DataGridView控件支持叠加数据绑定
- WinForm中comboBox控件数据绑定实现方法
- 我的ASPxGridView控件的数据是在后台绑定的,但是实现不了筛选和分页的功能,只能显示一页的数据?
- c# 如何向comboBox中绑定数据库中指定的数据信息;
- DataGridView 控件中轻松设置DataGridViewComboBoxColumn数据绑定属性。
- 使用数据绑定控件实现增、删、改
- KeyValuePair<byte, string> 类型的数据如何绑定到ComboBox控件上
- 在Visual Studio 2005的DataGridView控件中加入ComboBox下拉列表框的实现(C#)
- WinForm控件复杂数据绑定常用数据源(如:Dictionary)(对Combobox,DataGridView等控件DataSource赋值的多种方法)
- C# winform combobox 在绑定数据之后插入一项选择项
- Android Studio中Spinner控件的数据绑定实现
- 打造Android集合控件数据绑定(支持添加监听,支持AbsListView与RecycleView,支持异步加载等)(三)具体实现
- 在C#中使用组合框数据绑定的问题
- c# comboBox与数据库中的数据绑定