新版介绍及源码:.Net强大的列表控件XPTable【进阶版】
-----------------------------------------------------------------------------------------------------------------------
XPTable的大名,想必C#开发的人都有所耳闻,使用下来确实强大,在表格中添加下拉列表、进度条、图标等非常容易,灵活方便。当添加大量数据时,和.Net自带的ListView对比过,速度快很多!
XPTable最重要的是开源,可根据自己的需要修改,有bug也可想办法解决。我就对其进行了若干处改进,解决了部分bug。源代码写的非常标准,架构设计也很值得借鉴,研读源代码本身就是个学习提高的过程。真心感谢将如此完美的代码公开分享的人,作为点滴回报,也将自己修改后的源码放出,供大家参考,和原作者的贡献比起来,我这点小小的修改就如沧海一粟,不足为道了。
我修改过的代码和解决的问题列示如下(下载我的源代码,在项目中搜索chenbo,就能看到修改注释):
1、...\Models\Table.cs Line 2118,2153
解决问题:在某些情况下(任意调整窗口大小,XPTable的Anchor设置为随窗口大小自适应调整)会抛System.ArgumentOutOfRangeException异常,vScrollBar.LargeChange不能小于0
2、...\Models\Table.cs Line 5598,5606
解决问题:在列头Resizing状态下双击鼠标,应根据该列数据中最长的一行调整当前列宽度,目前仅对TextColumn和NumberColumn有效
3、...\Models\Table.cs Line 6134
解决问题:在列头Resizing状态下单击鼠标,避免OnMouseUp激发列宽的调整。应该双击或者调整宽度后才能激发
4、...\Models\Table.cs Line 6373
解决问题:根据原代码,如果Table允许多选,选中多行后,点鼠标右键将自动选择鼠标所在行,修改后,多选的行依然选中
这个问题借鉴了“恶猫的尾巴”的代码:http://emao.me/tag/XpTable/,在此感谢!
5、...\Models\Table.cs Line 6627
解决问题:鼠标在列头为Resizing图标时,移动到数据区域不会自动变为默认图标
6、...\Models\Table.cs Line 7229
解决问题:解决列头的对齐方式始终是靠左的问题
7、...\Renderers\NumberCellRenderer.cs Line 661
解决问题:为了实现Table.cs的函数CalColumnWidth中实现对NumberColumn列格式化数据宽度的计算
8、... 刚下载源码后即发现的问题,好像是某个函数col参数有问题,具体不记得哪个文件哪行代码了
我修改后的源代码和Dll下载链接(VS2008 .NetFramework 2.0)
自己写了控制类(TableCtrl.cs)来操作XPTable,使用起来更方便
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using XPTable;
using XPTable.Models;
using XPTable.Editors;
namespace ProgramModule
{
struct Key
{
public string name;
public object value;
};
class TableKey
{
private List<Key> m_keys;
public TableKey()
{
m_keys = new List<Key>();
}
public void AddKey(string name, object value)
{
Key key;
key.name = name;
key.value = value;
m_keys.Add(key);
}
public int Count
{
get
{
return m_keys.Count;
}
}
public string GetKeyName(int index)
{
if (index < 0 || index >= Count)
{
return "";
}
else
{
return m_keys[index].name;
}
}
public object GetKeyValue(int index)
{
if (index < 0 || index >= Count)
{
return null;
}
else
{
return m_keys[index].value;
}
}
};
static class TableCtrl
{
const int COLOR_WINDOW = 5;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int GetSysColor(int nIndex);
public static Color GetSysWindowColor()
{
Color color;
int iColor = GetSysColor(COLOR_WINDOW);
color = Color.FromArgb(255, Color.FromArgb(iColor));
return color;
}
public static void InitTable(ref Table table)
{
try
{
table.NoItemsText = "";
table.GridLines = GridLines.Both;
table.ColumnModel = new ColumnModel();
table.TableModel = new TableModel();
table.TableModel.RowHeight = 18;
TextColumn textColKey = new TextColumn("key", 70);
textColKey.Visible = false;
table.ColumnModel.Columns.Add(textColKey);
table.FullRowSelect = true;
table.HideSelection = false;
table.BackColor = GetSysWindowColor();
table.SortedColumnBackColor = Color.FromArgb(100, Color.WhiteSmoke);
}
catch (System.Exception ex)
{
GlobalFunction.MsgBoxException(ex.Message, "InitTable");
}
}
public static void AddColumn(ref Table table, Column column)
{
column.Editable = false;
column.Sortable = true;
table.ColumnModel.Columns.Add(column);
}
public static void AddColumn(ref Table table, Column column, bool editable, bool sortable)
{
column.Editable = editable;
column.Sortable = sortable;
table.ColumnModel.Columns.Add(column);
}
public static void AddColumn(ref Table table, Column column, bool editable, bool sortable, ColumnAlignment alignment)
{
column.Editable = editable;
column.Sortable = sortable;
column.Alignment = alignment;
table.ColumnModel.Columns.Add(column);
}
public static void AddNumColumn(ref Table table, NumberColumn column, bool editable, bool sortable, bool showUpDownButton, double minValue, double MaxValue, string format, ColumnAlignment alignment)
{
column.Editable = editable;
column.Sortable = sortable;
column.ShowUpDownButtons = showUpDownButton;
column.Minimum = Convert.ToDecimal(minValue);
column.Maximum = Convert.ToDecimal(MaxValue);
column.Format = format;
column.Alignment = alignment;
table.ColumnModel.Columns.Add(column);
}
//public static int AddNewRow(ref Table table)
//{
// Row row = new Row();
// for (int i = 0; i < table.ColumnModel.Columns.Count; i++ )
// {
// row.Cells.Add(new Cell());
// }
// return table.TableModel.Rows.Add(row);
//}
public static Row AddNewRow(ref Table table)
{
try
{
Row row = new Row();
for (int i = 0; i < table.ColumnModel.Columns.Count; i++)
{
row.Cells.Add(new Cell());
}
table.TableModel.Rows.Add(row);
return row;
}
catch (System.Exception e)
{
GlobalFunction.MsgBoxException(e.Message, "AddNewRow");
return null;
}
}
public static Row AddNewRow(ref Table table, string key)
{
try
{
foreach (Row row1 in table.TableModel.Rows)
{
if (row1.Cells[0].Text == key)
{
GlobalFunction.MsgBoxError("key is not unique");
return null;
}
}
Row row = new Row();
for (int i = 0; i < table.ColumnModel.Columns.Count; i++)
{
row.Cells.Add(new Cell());
}
row.Cells[0].Text = key;
table.TableModel.Rows.Add(row);
return row;
}
catch (System.Exception e)
{
GlobalFunction.MsgBoxException(e.Message, "AddNewRow");
return null;
}
}
public static void RemoveRow(ref Table table, int rowIndex)
{
try
{
table.TableModel.Rows.RemoveAt(rowIndex);
}
catch (System.Exception e)
{
MessageBox.Show("RemoveRow:" + e.Message);
}
}
public static void RemoveRow(ref Table table, Row row)
{
try
{
table.TableModel.Rows.Remove(row);
}
catch (System.Exception e)
{
GlobalFunction.MsgBoxException(e.Message, "RemoveRow");
}
}
public static void RemoveRowAll(ref Table table)
{
try
{
table.TableModel.Rows.Clear();
}
catch (System.Exception e)
{
MessageBox.Show("RemoveRowAll:" + e.Message);
}
}
public static void SetTableValue(ref Table table, int rowIndex, string colName, object value)
{
try
{
Column targetCol = null;
int colIndex = -1;
if (rowIndex < 0 || rowIndex >= table.TableModel.Rows.Count)
{
return;
}
for (int i = 0; i < table.ColumnModel.Columns.Count; i++)
{
if (table.ColumnModel.Columns[i].Text == colName)
{
targetCol = table.ColumnModel.Columns[i];
colIndex = i;
break;
}
}
if (colIndex == -1)
{
return;
}
if (targetCol is TextColumn || targetCol is ComboBoxColumn || targetCol is ButtonColumn)
{
table.TableModel.Rows[rowIndex].Cells[colIndex].Text = value.ToString();
}
else if (targetCol is CheckBoxColumn)
{
table.TableModel.Rows[rowIndex].Cells[colIndex].Checked = (bool)value;
}
else if (targetCol is ImageColumn)
{
table.TableModel.Rows[rowIndex].Cells[colIndex].Image = (Image)value;
}
else if (targetCol is NumberColumn)
{
if (GlobalFunction.IsNumeric(value.ToString()))
{
table.TableModel.Rows[rowIndex].Cells[colIndex].Data = Convert.ToDouble(value);
}
}
else
{
table.TableModel.Rows[rowIndex].Cells[colIndex].Data = value;
}
}
catch (System.Exception e)
{
GlobalFunction.MsgBoxException(e.Message, "SetTableValue");
}
}
public static void SetTableValue(ref Table table, int rowIndex, int colIndex, object value)
{
try
{
if (colIndex <= 0)
{
return;
}
Column targetCol = table.ColumnModel.Columns[colIndex];
if (targetCol is TextColumn || targetCol is ComboBoxColumn || targetCol is ButtonColumn)
{
table.TableModel.Rows[rowIndex].Cells[colIndex].Text = value.ToString();
}
else if (targetCol is CheckBoxColumn)
{
table.TableModel.Rows[rowIndex].Cells[colIndex].Checked = (bool)value;
}
else if (targetCol is ImageColumn)
{
table.TableModel.Rows[rowIndex].Cells[colIndex].Image = (Image)value;
}
else if (targetCol is NumberColumn)
{
if (GlobalFunction.IsNumeric(value.ToString()))
{
table.TableModel.Rows[rowIndex].Cells[colIndex].Data = Convert.ToDouble(value);
}
}
else
{
table.TableModel.Rows[rowIndex].Cells[colIndex].Data = value;
}
}
catch (System.Exception e)
{
GlobalFunction.MsgBoxException(e.Message, "SetTableValue");
}
}
public static void SetTableValue(ref Table table, Row row, string colName, object value)
{
try
{
Column targetCol = null;
int colIndex = -1;
if (row == null)
{
return;
}
for (int i = 0; i < table.ColumnModel.Columns.Count; i++)
{
if (table.ColumnModel.Columns[i].Text == colName)
{
targetCol = table.ColumnModel.Columns[i];
colIndex = i;
break;
}
}
if (colIndex == -1)
{
return;
}
if (targetCol is TextColumn || targetCol is ComboBoxColumn || targetCol is ButtonColumn)
{
row.Cells[colIndex].Text = value.ToString();
}
else if (targetCol is CheckBoxColumn)
{
row.Cells[colIndex].Checked = (bool)value;
}
else if (targetCol is ImageColumn)
{
row.Cells[colIndex].Image = (Image)value;
}
else if (targetCol is NumberColumn)
{
string val = "";
if (GlobalFunction.FormatNumber(value.ToString(), 8, ref val))
{
row.Cells[colIndex].Data = Convert.ToDouble(val);
}
//if (GlobalFunction.IsNumeric(value.ToString()))
//{
//}
}
else
{
row.Cells[colIndex].Data = value;
}
}
catch (System.Exception e)
{
GlobalFunction.MsgBoxException(e.Message, "SetTableValue");
}
}
public static void SetTableValueCheckbox(ref Table table, int rowIndex, string colName, string text, bool check)
{
try
{
Column targetCol = null;
int colIndex = -1;
if (rowIndex < 0 || rowIndex >= table.TableModel.Rows.Count)
{
return;
}
for (int i = 0; i < table.ColumnModel.Columns.Count; i++)
{
if (table.ColumnModel.Columns[i].Text == colName)
{
targetCol = table.ColumnModel.Columns[i];
colIndex = i;
break;
}
}
if (colIndex == -1)
{
return;
}
if (targetCol is CheckBoxColumn)
{
table.TableModel.Rows[rowIndex].Cells[colIndex].Text = text;
table.TableModel.Rows[rowIndex].Cells[colIndex].Checked = check;
}
}
catch (System.Exception e)
{
GlobalFunction.MsgBoxException(e.Message, "SetTableValueCheckbox");
}
}
public static void SetTableValueCheckbox(ref Table table, Row row, string colName, string text, bool check)
{
try
{
Column targetCol = null;
int colIndex = -1;
if (row == null)
{
return;
}
for (int i = 0; i < table.ColumnModel.Columns.Count; i++)
{
if (table.ColumnModel.Columns[i].Text == colName)
{
targetCol = table.ColumnModel.Columns[i];
colIndex = i;
break;
}
}
if (colIndex == -1)
{
return;
}
if (targetCol is CheckBoxColumn)
{
row.Cells[colIndex].Text = text;
row.Cells[colIndex].Checked = check;
}
}
catch (System.Exception e)
{
GlobalFunction.MsgBoxException(e.Message, "SetTableValueCheckbox");
}
}
public static void SetTableValueImage(ref Table table, int rowIndex, string colName, string text, Image image)
{
try
{
Column targetCol = null;
int colIndex = -1;
if (rowIndex < 0 || rowIndex >= table.TableModel.Rows.Count)
{
return;
}
for (int i = 0; i < table.ColumnModel.Columns.Count; i++)
{
if (table.ColumnModel.Columns[i].Text == colName)
{
targetCol = table.ColumnModel.Columns[i];
colIndex = i;
break;
}
}
if (colIndex == -1)
{
return;
}
if (targetCol is ImageColumn)
{
table.TableModel.Rows[rowIndex].Cells[colIndex].Text = text;
table.TableModel.Rows[rowIndex].Cells[colIndex].Image = image;
}
}
catch (System.Exception e)
{
GlobalFunction.MsgBoxException(e.Message, "SetTableValueImage");
}
}
public static void SetTableValueImage(ref Table table, Row row, string colName, string text, Image image)
{
try
{
Column targetCol = null;
int colIndex = -1;
if (row == null)
{
return;
}
for (int i = 0; i < table.ColumnModel.Columns.Count; i++)
{
if (table.ColumnModel.Columns[i].Text == colName)
{
targetCol = table.ColumnModel.Columns[i];
colIndex = i;
break;
}
}
if (colIndex == -1)
{
return;
}
if (targetCol is ImageColumn)
{
row.Cells[colIndex].Text = text;
row.Cells[colIndex].Image = image;
}
}
catch (System.Exception e)
{
GlobalFunction.MsgBoxException(e.Message, "SetTableValueImage");
}
}
public static object GetTableValue(Table table, int row, int col)
{
try
{
Column targetCol = null;
int colIndex = -1;
if (row < 0 || row >= table.TableModel.Rows.Count)
{
return null;
}
if (col < 0 || col >= table.ColumnModel.Columns.Count)
{
return null;
}
targetCol = table.ColumnModel.Columns[col];
colIndex = col;
if (colIndex == -1)
{
return null;
}
if (targetCol is TextColumn || targetCol is ComboBoxColumn || targetCol is ButtonColumn)
{
if (table.TableModel.Rows[row].Cells[colIndex].Text == null)
{
return "";
}
else
{
return table.TableModel.Rows[row].Cells[colIndex].Text;
}
}
else if (targetCol is CheckBoxColumn)
{
return table.TableModel.Rows[row].Cells[colIndex].Checked;
}
else
{
return table.TableModel.Rows[row].Cells[colIndex].Data;
}
}
catch (System.Exception e)
{
GlobalFunction.MsgBoxException(e.Message, "GetTableValue");
return null;
}
}
public static string GetTableValueString(Table table, int row, int col)
{
try
{
Column targetCol = null;
int colIndex = -1;
if (row < 0 || row >= table.TableModel.Rows.Count)
{
return "";
}
if (col < 0 || col >= table.ColumnModel.Columns.Count)
{
return "";
}
targetCol = table.ColumnModel.Columns[col];
colIndex = col;
if (colIndex == -1)
{
return "";
}
if (targetCol is TextColumn || targetCol is ComboBoxColumn || targetCol is ButtonColumn)
{
if (table.TableModel.Rows[row].Cells[colIndex].Text == null)
{
return "";
}
else
{
return table.TableModel.Rows[row].Cells[colIndex].Text;
}
}
else if (targetCol is CheckBoxColumn)
{
return table.TableModel.Rows[row].Cells[colIndex].Checked.ToString();
}
else
{
return table.TableModel.Rows[row].Cells[colIndex].Data.ToString();
}
}
catch (System.Exception e)
{
GlobalFunction.MsgBoxException(e.Message, "GetTableValueString");
return "";
}
}
public static object GetTableValue(Table table, int row, string colName)
{
try
{
Column targetCol = null;
int colIndex = -1;
if (row < 0 || row >= table.TableModel.Rows.Count)
{
return null;
}
for (int i = 0; i < table.ColumnModel.Columns.Count; i++)
{
if (table.ColumnModel.Columns[i].Text == colName)
{
targetCol = table.ColumnModel.Columns[i];
colIndex = i;
break;
}
}
if (colIndex == -1)
{
return null;
}
if (targetCol is TextColumn || targetCol is ComboBoxColumn || targetCol is ButtonColumn)
{
if (table.TableModel.Rows[row].Cells[colIndex].Text == null)
{
return "";
}
else
{
return table.TableModel.Rows[row].Cells[colIndex].Text;
}
}
else if (targetCol is CheckBoxColumn)
{
return table.TableModel.Rows[row].Cells[colIndex].Checked;
}
else
{
return table.TableModel.Rows[row].Cells[colIndex].Data;
}
}
catch (System.Exception e)
{
GlobalFunction.MsgBoxException(e.Message, "GetTableValue");
return null;
}
}
public static string GetTableValueString(Table table, int row, string colName)
{
try
{
Column targetCol = null;
int colIndex = -1;
if (row < 0 || row >= table.TableModel.Rows.Count)
{
return "";
}
for (int i = 0; i < table.ColumnModel.Columns.Count; i++)
{
if (table.ColumnModel.Columns[i].Text == colName)
{
targetCol = table.ColumnModel.Columns[i];
colIndex = i;
break;
}
}
if (colIndex == -1)
{
return "";
}
if (targetCol is TextColumn || targetCol is ComboBoxColumn || targetCol is ButtonColumn)
{
if (table.TableModel.Rows[row].Cells[colIndex].Text == null)
{
return "";
}
else
{
return table.TableModel.Rows[row].Cells[colIndex].Text;
}
}
else if (targetCol is CheckBoxColumn)
{
return table.TableModel.Rows[row].Cells[colIndex].Checked.ToString();
}
else
{
return table.TableModel.Rows[row].Cells[colIndex].Data.ToString();
}
}
catch (System.Exception e)
{
GlobalFunction.MsgBoxException(e.Message, "GetTableValueString");
return "";
}
}
public static Row GetTableRowByKey(ref Table table, string key)
{
try
{
foreach (Row row in table.TableModel.Rows)
{
if (row.Cells[0].Text == key)
{
return row;
}
}
return null;
}
catch (System.Exception e)
{
GlobalFunction.MsgBoxException(e.Message, "GetTableRowByKey");
return null;
}
}
public static int GetTableRowByKey(ref Table table, TableKey keys)
{
try
{
int i, j;
int row = -1;
int keyCount;
keyCount = keys.Count;
if (keyCount <= 0)
{
return -1;
}
for (i = 0; i < table.TableModel.Rows.Count; i++)
{
for (j = 0; j < keyCount; j++)
{
if (!object.Equals(GetTableValue(table, i, keys.GetKeyName(j)), keys.GetKeyValue(j)))
{
break;
}
}
if (j == keyCount)
{
row = i;
break;
}
}
return row;
}
catch (System.Exception e)
{
GlobalFunction.MsgBoxException(e.Message, "GetTableRowByKey");
return -1;
}
}
public static int GetColumnIndexByName(Table table, string strColName)
{
try
{
if (table.ColumnModel.Columns.Count <= 0)
{
return -1;
}
else
{
for (int i = 0; i < table.ColumnModel.Columns.Count; i++)
{
if (table.ColumnModel.Columns[i].Text == strColName)
{
return i;
}
}
return -1;
}
}
catch (System.Exception ex)
{
GlobalFunction.MsgBoxException(ex.Message, "GetColumnIndexByName");
return -1;
}
}
public static void SetCellBackColor(ref Table table, int row, string strColName, Color color)
{
try
{
if (row >= table.TableModel.Rows.Count || row < 0)
{
return;
}
int col = GetColumnIndexByName(table, strColName);
if (col == -1)
{
return;
}
table.TableModel.Rows[row].Cells[col].BackColor = color;
}
catch (System.Exception ex)
{
GlobalFunction.MsgBoxException(ex.Message, "SetCellBackColor");
}
}
public static void SetRowBackColor(ref Table table, int row, Color color)
{
try
{
if (row >= table.TableModel.Rows.Count || row < 0)
{
return;
}
table.TableModel.Rows[row].BackColor = color;
//for (int col = 0; col < table.ColumnModel.Columns.Count; col++)
//{
// table.TableModel.Rows[row].Cells[col].BackColor = color;
//}
}
catch (System.Exception ex)
{
GlobalFunction.MsgBoxException(ex.Message, "SetRowBackColor");
}
}
public static void SetCellForeColor(ref Table table, int row, string strColName, Color color)
{
try
{
if (row >= table.TableModel.Rows.Count || row < 0)
{
return;
}
int col = GetColumnIndexByName(table, strColName);
if (col == -1)
{
return;
}
table.TableModel.Rows[row].Cells[col].ForeColor = color;
}
catch (System.Exception ex)
{
GlobalFunction.MsgBoxException(ex.Message, "SetCellForeColor");
}
}
public static void SetRowForeColor(ref Table table, int row, Color color)
{
try
{
if (row >= table.TableModel.Rows.Count || row < 0)
{
return;
}
table.TableModel.Rows[row].ForeColor = color;
//for (int col = 0; col < table.ColumnModel.Columns.Count; col++)
//{
// table.TableModel.Rows[row].Cells[col].ForeColor = color;
//}
}
catch (System.Exception ex)
{
GlobalFunction.MsgBoxException(ex.Message, "SetRowForeColor");
}
}
public static void SetColumnBackColor(ref Table table, string strColName, Color color)
{
try
{
if (table.TableModel.Rows.Count <= 0)
{
return;
}
int col = GetColumnIndexByName(table, strColName);
if (col == -1)
{
return;
}
foreach (Row row in table.TableModel.Rows)
{
row.Cells[col].BackColor = color;
}
}
catch (System.Exception ex)
{
GlobalFunction.MsgBoxException(ex.Message, "SetColumnBackColor");
}
}
public static void SetColumnForeColor(ref Table table, string strColName, Color color)
{
try
{
if (table.TableModel.Rows.Count <= 0)
{
return;
}
int col = GetColumnIndexByName(table, strColName);
if (col == -1)
{
return;
}
foreach (Row row in table.TableModel.Rows)
{
row.Cells[col].ForeColor = color;
}
}
catch (System.Exception ex)
{
GlobalFunction.MsgBoxException(ex.Message, "SetColumnForeColor");
}
}
public static void SelectRow(ref Table table, int rowIndex)
{
try
{
if (rowIndex >= 0 && rowIndex < table.TableModel.Rows.Count)
{
table.TableModel.Selections.SelectCells(rowIndex, 0, rowIndex, table.ColumnModel.Columns.Count - 1);
}
}
catch (System.Exception ex)
{
GlobalFunction.MsgBoxException(ex.Message, "SelectRow");
}
}
public static void Sort(ref Table table, string strColName, SortOrder order, bool stable)
{
try
{
if (table.TableModel.Rows.Count <= 0)
{
return;
}
int col = GetColumnIndexByName(table, strColName);
if (col == -1)
{
return;
}
else
{
table.Sort(col, order, stable);
}
}
catch (System.Exception ex)
{
GlobalFunction.MsgBoxException(ex.Message, "Sort");
}
}
}
}