该程序主要参考codeProject上的一个程序,链接已失去,不过要想其致敬!
默认的combobox是不提供多列显示的,所以这里要用绘制的方法显示该功能,主要是重写combobox。其中combobox有个属性DrawMode,需将其设为DrawMode.OwnerDrawVariable,原因如下:从MSDN摘录.
| Normal | 控件中的所有元素都由操作系统绘制,并且元素大小都相等。 |
| OwnerDrawFixed | 控件中的所有元素都是手动绘制的,并且元素大小都相等。 |
| OwnerDrawVariable | 控件中的所有元素都由手动绘制,元素大小可能不相等。 |
具体步骤如下:实例以datatable为数据源,数据源也可以是arraylist或通过add()方法添加
int columnPadding = 5;
private float[] columnWidths = new float[0]; //项宽度
private String[] columnNames = new String[0]; //项名称
private int valueMemberColumnIndex = 0; //valueMember属性列所在的索引
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**/
/// <summary>
/// 绑定数据源或更改数据源时发生
/// </summary>
/// <param name="e"></param>
protected
override
void
OnDataSourceChanged(EventArgs e)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
base.OnDataSourceChanged(e);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
InitializeColumns();
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**/
/// <summary>
/// 设置ValueMember属性发生
/// </summary>
/// <param name="e"></param>
protected
override
void
OnValueMemberChanged(EventArgs e)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
base.OnValueMemberChanged(e);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
InitializeValueMemberColumn();
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**/
/// <summary>
/// 显示下拉框的时候触发
/// </summary>
/// <param name="e"></param>
protected
override
void
OnDropDown(EventArgs e)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
base.OnDropDown(e);
this.DropDownWidth = (int)CalculateTotalWidth(); //计算combobox下拉框的总宽度
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**/
/// <summary>
/// 初始化数据源各列的名称
/// </summary>
private
void
InitializeColumns()
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
PropertyDescriptorCollection propertyDescriptorCollection = DataManager.GetItemProperties();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
columnWidths = new float[propertyDescriptorCollection.Count];
columnNames = new String[propertyDescriptorCollection.Count];
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
for (int colIndex = 0; colIndex < propertyDescriptorCollection.Count; colIndex++)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
String name = propertyDescriptorCollection[colIndex].Name;
columnNames[colIndex] = name;
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**/
/// <summary>
/// 返回ValueMember在显示列中的索引位置
/// </summary>
private
void
InitializeValueMemberColumn()
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
int colIndex = 0;
foreach (String columnName in columnNames)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (String.Compare(columnName, ValueMember, true, CultureInfo.CurrentUICulture) == 0)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
valueMemberColumnIndex = colIndex;
break;
}
colIndex++;
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**/
/// <summary>
/// 计算combobox下拉框的总宽度
/// </summary>
/// <returns></returns>
private
float
CalculateTotalWidth()
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
columnPadding = 5;
float totWidth = 0;
foreach (int width in columnWidths)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
totWidth += (width + columnPadding);
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//总宽度加上垂直滚动条的宽度
return totWidth + SystemInformation.VerticalScrollBarWidth;
}
绘制字符串所使用的两个方法:
/**/
/// <summary>
/// 获得各列的宽度和项的总宽度
/// 引发 MeasureItem 事件
/// </summary>
/// <param name="e"></param>
protected
override
void
OnMeasureItem(MeasureItemEventArgs e)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
base.OnMeasureItem(e);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
if (DesignMode)
return;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
for (int colIndex = 0; colIndex < columnNames.Length; colIndex++)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//如果 ListControl 项是被给定了该项以及属性名称的对象的属性,则返回该项的当前值
string item = Convert.ToString(FilterItemOnProperty(Items[e.Index], columnNames[colIndex]));
SizeF sizeF = e.Graphics.MeasureString(item, Font); //返回显示项字符串的大小
columnWidths[colIndex] = Math.Max(columnWidths[colIndex], sizeF.Width);
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
float totWidth = CalculateTotalWidth(); //计算combobox下拉框项宽度
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
e.ItemWidth = (int)totWidth; //设置combobox下拉框项宽度
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**/
/// <summary>
/// 绘制下拉框的内容
/// 引发 DrawItem 事件
/// </summary>
/// <param name="e"></param>
protected
override
void
OnDrawItem(DrawItemEventArgs e)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
base.OnDrawItem(e);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
if (DesignMode)
return;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
e.DrawBackground();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Rectangle boundsRect = e.Bounds;
int lastRight = 0;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
using (Pen linePen = new Pen(SystemColors.GrayText))
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
using (SolidBrush brush = new SolidBrush(ForeColor))
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (columnNames.Length == 0)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
e.Graphics.DrawString(Convert.ToString(Items[e.Index]), Font, brush, boundsRect);
}
else
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//循环各列
for (int colIndex = 0; colIndex < columnNames.Length; colIndex++)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
string item = Convert.ToString(FilterItemOnProperty(Items[e.Index], columnNames[colIndex]));
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
boundsRect.X = lastRight; //列的左边位置
boundsRect.Width = (int)columnWidths[colIndex] + columnPadding; //列的宽度
lastRight = boundsRect.Right;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
if (colIndex == valueMemberColumnIndex)//如果是valueMember项
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
using (Font boldFont = new Font(Font, FontStyle.Bold))
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//绘制项的内容
e.Graphics.DrawString(item, boldFont, brush, boundsRect);
}
}
else
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//绘制项的内容
e.Graphics.DrawString(item, Font, brush, boundsRect);
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//绘制各项间的竖线
if (colIndex < columnNames.Length - 1)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
e.Graphics.DrawLine(linePen, boundsRect.Right, boundsRect.Top, boundsRect.Right, boundsRect.Bottom);
}
}
}
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
e.DrawFocusRectangle();
}
界面层绑定数据源:
DataTable dataTable
=
new
DataTable(
"
Employees
"
);
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
dataTable.Columns.Add(
"
Employee ID
"
,
typeof
(String));
dataTable.Columns.Add(
"
Name
"
,
typeof
(String));
dataTable.Columns.Add(
"
Country
"
,
typeof
(String));
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
dataTable.Rows.Add(
new
String[]
{ "1", "James", "USA" }
);
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
dataTable.Rows.Add(
new
String[]
{ "2", "Mary", "UK" }
);
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
dataTable.Rows.Add(
new
String[]
{ "3", "Jack", "Japan" }
);
有需要源码的朋友同样可以到我的群中下载.