XPTable - .NET ListView 遇上 Java 的 JTable






4.97/5 (441投票s)
2005 年 9 月 11 日
12分钟阅读

7082045

55356
一个基于 Java 的 JTable 的完全可定制的 ListView 风格控件。
目录
引言
在我正在进行的一个项目中,我需要一个高度定制的 ListView
—— 一个能够允许在任何列中包含复选框和图像,提供 ComboBox
和 NumericUpDown
用于编辑,并且能够轻松地进行数据传入和传出的控件。任何尝试过定制 ListView
的人都知道,要想把它按照自己的意愿进行修改是多么痛苦,所以我决定从头开始创建一个。我来自 Java 背景,所以决定在一定程度上松散地参考 Java 的 JTable
。
特点
- 完全可定制的视觉外观——从列到行和单元格。
- 支持 Windows XP 视觉样式。
- 强大的渲染器,使单元格能够像控件一样工作。
- 轻松添加您自己的自定义渲染器和编辑器。
- 列可以被隐藏。
- 行、列或单个单元格可以被禁用。
- 列和单元格的 ToolTips (工具提示)。
- 还有更多……
XPTable
XPTable
由以下组件组成:
- 一个
Table
(表) - 一个
ColumnModel
(列模型) 及其Column
s (列) - 一个
TableModel
(表模型) 及其Row
s (行) 和Cell
s (单元格) Renderer
s (渲染器) 和Editor
s (编辑器)
我不会详细介绍前三个方面,只展示第四和第五点的一些基本知识,否则本文会比现在更长。如果您想了解任何一个主题的更多细节,您应该阅读随文档提供的用户指南。
使用 XPTable
在使用 XPTable
之前,您需要在项目的“引用”部分添加对 XPTable.dll 的引用。
要将 XPTable.dll 添加到工具箱,您可以
- 从菜单中选择 工具 -> 添加/删除工具箱项,或
- 右键单击工具箱,选择 添加/删除项。
然后浏览 XPTable.dll 并按 OK。然后您可以将控件拖到您的窗体上。
注意: 如果您重新编译源代码,您将需要重新签名 XPTable.dll,否则 Visual Studio 在您尝试将其添加到工具箱时可能会抛出异常。
- 打开 VS .NET 命令提示符,并将目录更改为指向 XPTable\bin\Release 目录。
- 然后输入 "sn -R XPTable.dll ..\..\XPTable.snk" (当然,不包括引号)。
之后,您应该能够将其添加到工具箱。
之后,您只需将 Table
、ColumnModel
和 TableModel
拖到您的窗体上,设置 Table
的 ColumnModel
和 TableModel
属性,并在 ColumnModel
中添加 Column
s (列),在 TableModel
中添加 Row
s (行) 和 Cell
s (单元格)。
或者,如果您喜欢代码
Table table = new Table();
ColumnModel columnModel = new ColumnModel();
TableModel tableModel = new TableModel();
// set the Table's ColumModel and TableModel
table.ColumnModel = columnModel;
table.TableModel = tableModel;
// add some Columns to the ColumnModel
columnModel.Columns.Add(new TextColumn("Text"));
columnModel.Columns.Add(new CheckBoxColumn("CheckBox"));
columnModel.Columns.Add(new ButtonColumn("Button"));
// add some Rows and Cells to the TableModel
tableModel.Rows.Add(new Row());
tableModel.Rows[0].Cells.Add(new Cell("Text 1"));
tableModel.Rows[0].Cells.Add(new Cell("CheckBox 1", true));
tableModel.Rows[0].Cells.Add(new Cell("Button 1"));
tableModel.Rows.Add(new Row());
tableModel.Rows[1].Cells.Add(new Cell("Text 2"));
tableModel.Rows[1].Cells.Add(new Cell("CheckBox 2", false));
tableModel.Rows[1].Cells.Add(new Cell("Button 2"));
表格
Table
是一个“简单”的对象,因为它实际上不包含或不知道如何绘制它将要显示的数据。相反,它使用 ColumnModel
来跟踪它的 Column
s (列),使用 TableModel
来跟踪它的 Row
s (行) 和 Cell
s (单元格),以及使用 Renderer
s (渲染器) 和 Editor
s (编辑器) 来绘制和编辑它的数据。Table
的主要作用是管理绘制操作,并将事件传递给 Renderer
s (渲染器) 和 Editor
s (编辑器),以便它们可以采取适当的操作。
ColumnModel (列模型)
ColumnModel
包含一个 Column
s (列) 的集合,这些列将在 Table
中显示。它还跟踪是否为特定 Column
创建了 CellRenderer
(单元格渲染器) 或 CellEditor
(单元格编辑器)。
Columns
在仔细考虑了实现 Column
s (列) 的最佳方法后,我决定采用与 DataGrid
相同的方法——即根据其 Cell
s (单元格) 将包含的数据类型来定义不同类型的 Column
s (列)。以下 Column
(列) 类型可用:
Column
- 所有Column
s (列) 的基类。TextColumn
- 一个Column
(列),其Cell
s (单元格) 显示为字符串。ButtonColumn
- 一个Column
(列),其Cell
s (单元格) 显示为Button
s (按钮)。CheckBoxColumn
- 一个Column
(列),其Cell
s (单元格) 显示为CheckBox
es (复选框)。ImageColumn
- 一个Column
(列),其Cell
s (单元格) 显示为Image
s (图像)。NumberColumn
- 一个Column
(列),其Cell
s (单元格) 显示为数字。ProgressBarColumn
- 一个Column
(列),其Cell
s (单元格) 显示为ProgressBar
s (进度条)。DropDownColumn
- 用于显示下拉框进行编辑的Column
s (列) 的基类。ComboBoxColumn
- 表示一个Column
(列),其Cell
s (单元格) 显示为ComboBox
es (组合框)。DateTimeColumn
- 表示一个Column
(列),其Cell
s (单元格) 包含DateTime
s (日期时间)。ColorColumn
- 表示一个Column
(列),其Cell
s (单元格) 包含Color
s (颜色)。
TableModel (表模型)
TableModel
包含一个 Row
s (行) 的集合,这些行将在 Table
中显示。
Rows
Row
表示 Table
中的一行,并包含一个 Cell
s (单元格) 的集合,这些单元格将在 Row
中显示。
格子
Cell
包含将在 Table
中显示的数据。
Renderers (渲染器)
如前所述,Table
不知道如何绘制 Cell
s (单元格) 或 Column
(列) 的标题。相反,它使用称为 Renderer
s (渲染器) 的对象来完成所有绘制工作。Java 网站将渲染器描述为“一个表用于将适当格式化数据的可配置印章,盖在每个单元格上”。
Table
使用两种不同类型的 Renderer
s (渲染器):CellRenderer
s (单元格渲染器),它们绘制 Cell
s (单元格),以及 HeaderRenderer
s (表头渲染器),它们绘制 Column
(列) 的标题。
CellRenderers (单元格渲染器)
CellRenderer
s (单元格渲染器) 是强大的对象,因为它们允许 Cell
s (单元格) 看起来和行为都像 Windows 控件,而不会消耗任何额外的资源。
下面的列表显示了 XPTable
提供的所有 CellRenderer
s (单元格渲染器):
ICellRenderer
- 公开Cell
(单元格) 渲染器提供的通用方法。CellRenderer
- 所有Cell
(单元格) 渲染器的基类。TextCellRenderer
- 一个CellRenderer
(单元格渲染器),它将Cell
(单元格) 内容绘制为字符串。ButtonCellRenderer
- 一个CellRenderer
(单元格渲染器),它将Cell
(单元格) 内容绘制为Button
s (按钮)。CheckBoxCellRenderer
- 一个CellRenderer
(单元格渲染器),它将Cell
(单元格) 内容绘制为CheckBox
es (复选框)。ImageCellRenderer
- 一个CellRenderer
(单元格渲染器),它将Cell
(单元格) 内容绘制为Image
s (图像)。NumberCellRenderer
- 一个CellRenderer
(单元格渲染器),它将Cell
(单元格) 内容绘制为数字。ProgressBarCellRenderer
- 一个CellRenderer
(单元格渲染器),它将Cell
(单元格) 内容绘制为ProgressBar
(进度条)。DropDownCellRenderer
- 用于绘制Cell
(单元格) 内容如同ComboBox
es (组合框) 的CellRenderer
s (单元格渲染器) 的基类。ComboBoxCellRenderer
- 一个CellRenderer
(单元格渲染器),它将Cell
(单元格) 内容绘制为ComboBox
(组合框)。ColorCellRenderer
- 一个CellRenderer
(单元格渲染器),它将Cell
(单元格) 内容绘制为Color
s (颜色)。DateTimeCellRenderer
- 一个CellRenderer
(单元格渲染器),它将Cell
(单元格) 内容绘制为DateTime
(日期时间)。
下图显示了每个 CellRenderer
(单元格渲染器) 的默认输出。
创建自定义 CellRenderer (单元格渲染器)
如果您想创建自定义 CellRenderer
(单元格渲染器),您有两个选择:继承 CellRenderer
(单元格渲染器) 并重写 (至少) OnPaint
和 OnPaintBackground
方法 (最简单且推荐的方法),或者实现 ICellRenderer
(工作量很大)。
下面是 Table
内置 TextCellRenderer
(文本单元格渲染器) 的代码。
public class TextCellRenderer : CellRenderer
{
protected override void OnPaint(PaintCellEventArgs e)
{
base.OnPaint(e);
// don't bother going any further if the Cell is null
if (e.Cell == null)
{
return;
}
// make sure we have some text to draw
if (e.Cell.Text != null && e.Cell.Text.Length != 0)
{
// check whether the cell is enabled
if (e.Enabled)
{
e.Graphics.DrawString(e.Cell.Text, base.Font,
base.ForeBrush, base.ClientRectangle,
base.StringFormat);
}
else
{
e.Graphics.DrawString(e.Cell.Text, base.Font,
base.GrayTextBrush, base.ClientRectangle,
base.StringFormat);
}
}
// draw a focus rect around the cell if it is
// enabled and has focus
if (e.Focused && e.Enabled)
{
ControlPaint.DrawFocusRectangle(e.Graphics,
base.ClientRectangle);
}
}
}
对于更复杂的示例,请参阅随文档提供的用户指南。
HeaderRenderers (表头渲染器)
与用于每个列的 CellRenderer
s (单元格渲染器) 不同,Table
使用单个 HeaderRenderer
(表头渲染器) 来绘制所有 Column
(列) 的标题。
下面的列表显示了 XPTable
提供的所有 HeaderRenderer
s (表头渲染器):
IHeaderRenderer
- 公开Column
(列) 标题渲染器提供的通用方法。HeaderRenderer
- 用于绘制Column
(列) 标题的Renderer
s (渲染器) 的基类。XPHeaderRenderer
- 一个HeaderRenderer
(表头渲染器),它绘制 Windows XP 主题的Column
(列) 标题。GradientHeaderRenderer
- 一个HeaderRenderer
(表头渲染器),它绘制渐变色的Column
(列) 标题。FlatHeaderRenderer
- 一个HeaderRenderer
(表头渲染器),它绘制平坦的Column
(列) 标题。
下图展示了内置 HeaderRenderer
s (表头渲染器) 的实际效果。
您可以通过设置 Table
的 HeaderRenderer
属性来指定 Table
将使用的 HeaderRenderer
(表头渲染器)。
// get the table to use a FlatHeaderRenderer
// to draw the column headers
table.HeaderRenderer = new FlatHeaderRenderer();
创建自定义 HeaderRenderer (表头渲染器)
如果您想创建自定义 HeaderRenderer
(表头渲染器),您有两个选择:继承 HeaderRenderer
(表头渲染器) 并重写 (至少) OnPaint
和 OnPaintBackground
方法 (最简单且推荐的方法),或者实现 IHeaderRenderer
(工作量很大)。
下面是 Table
内置 XPHeaderRenderer
(XP 表头渲染器) 的代码。
public class XPHeaderRenderer : HeaderRenderer
{
protected override void OnPaintBackground(PaintHeaderEventArgs e)
{
base.OnPaintBackground(e);
if (e.Column == null)
{
ThemeManager.DrawColumnHeader(e.Graphics, e.HeaderRect,
ColumnHeaderStates.Normal);
}
else
{
ThemeManager.DrawColumnHeader(e.Graphics, e.HeaderRect,
(ColumnHeaderStates) e.Column.ColumnState);
}
}
protected override void OnPaint(PaintHeaderEventArgs e)
{
base.OnPaint(e);
// don't bother if we don't have a column
if (e.Column == null)
{
return;
}
Rectangle textRect = base.ClientRectangle;
Rectangle imageRect = Rectangle.Empty;
// check whether we can draw an image on the column header
if (e.Column.Image != null)
{
imageRect = base.CalcImageRect();
textRect.Width -= imageRect.Width;
textRect.X += imageRect.Width;
if (e.Column.ImageOnRight)
{
imageRect.X = base.ClientRectangle.Right - imageRect.Width;
textRect.X = base.ClientRectangle.X;
}
// column headers that aren't themed and are pressed need
// their contents shifted down and to the right by 1 pixel
if (!ThemeManager.VisualStylesEnabled &&
e.Column.ColumnState == ColumnState.Pressed)
{
imageRect.X += 1;
imageRect.Y += 1;
}
base.DrawColumnHeaderImage(e.Graphics, e.Column.Image,
imageRect, e.Column.Enabled);
}
// column headers that aren't themed and are pressed need
// their contents shifted down and to the right by 1 pixel
if (!ThemeManager.VisualStylesEnabled &&
e.Column.ColumnState == ColumnState.Pressed)
{
textRect.X += 1;
textRect.Y += 1;
}
// check whether we need to draw a sort arrow
if (e.Column.SortOrder != SortOrder.None)
{
// work out where to draw it
Rectangle arrowRect = base.CalcSortArrowRect();
// adjust the textRect to take the arrow into account
arrowRect.X = textRect.Right - arrowRect.Width;
textRect.Width -= arrowRect.Width;
base.DrawSortArrow(e.Graphics, arrowRect, e.Column.SortOrder,
e.Column.Enabled);
}
// check whether we have any text to draw
if (e.Column.Text == null)
{
return;
}
if (e.Column.Text.Length > 0 && textRect.Width > 0)
{
if (e.Column.Enabled)
{
e.Graphics.DrawString(e.Column.Text,
base.Font, base.ForeBrush,
textRect, base.StringFormat);
}
else
{
using (SolidBrush brush =
new SolidBrush(SystemPens.GrayText.Color))
{
e.Graphics.DrawString(e.Column.Text,
base.Font, brush,
textRect, base.StringFormat);
}
}
}
}
}
Editors (编辑器)
XPTable
包含五种内置编辑器:
ICellEditor
- 公开Cell
(单元格) 编辑器提供的通用方法。CellEditor
-Cell
(单元格) 编辑器的基类。TextCellEditor
- 用于编辑包含字符串的Cell
s (单元格) 的类。NumberCellEditor
- 用于编辑包含数字的Cell
s (单元格) 的类。DropDownCellEditor
- 用于编辑包含下拉按钮的Cell
s (单元格) 的基类。ComboBoxCellEditor
- 用于编辑看起来像ComboBox
(组合框) 的Cell
s (单元格) 的类。ColorCellEditor
- 用于编辑包含Color
s (颜色) 的Cell
s (单元格) 的类。DateTimeCellEditor
- 用于编辑包含DateTime
s (日期时间) 的Cell
s (单元格) 的类。IEditorUsesRendererButtons
- 指示CellEditor
(单元格编辑器) 在编辑期间使用其对应的CellRenderer
(单元格渲染器) 提供的按钮。
注意: 有关 IEditorUsesRendererButtons
的更多信息,请参阅随文档提供的用户指南。
下图展示了使用下拉控件编辑 Cell
(单元格) 内容的编辑器。
您可以使用 table
的 EditCell
方法以编程方式编辑 Cell
(单元格)。
// start editing the cell at (0, 0)
table.EditCell(0, 0);
// stop editing the cell and commit any changes
table.StopEditing();
// or cancel editing and ignore any changes
table.CancelEditing();
注意: 如果您想停止或取消编辑,请始终使用 table
的 StopEditing
或 CancelEditing
方法 (即使在实现自定义 CellEditor
(单元格编辑器) 时也是如此)。这会给 table
一个机会来执行任何必要的预处理,然后再调用 CellEditor
(单元格编辑器) 的 StopEditing
或 CancelEditing
方法。
创建自定义 CellEditor (单元格编辑器)
如果您想创建自定义 CellEditor
(单元格编辑器),您有两个选择:继承 CellEditor
(单元格编辑器) 并重写 (至少) SetEditValue
、SetCellValue
和 SetEditLocation
方法 (最简单且推荐的方法),或者实现 ICellEditor
(工作量很大)。
下面是 Table
内置 TextCellEditor
(文本单元格编辑器) 的代码:
public class TextCellEditor : CellEditor
{
public TextCellEditor() : base()
{
TextBox textbox = new TextBox();
textbox.AutoSize = false;
textbox.BorderStyle = BorderStyle.None;
base.Control = textbox;
}
// Sets the location and size of the CellEditor
protected override void SetEditLocation(Rectangle cellRect)
{
this.TextBox.Location = cellRect.Location;
this.TextBox.Size = new Size(cellRect.Width-1,
cellRect.Height-1);
}
// Sets the initial value of the
// editor based on the contents of
// the Cell being edited
protected override void SetEditValue()
{
this.TextBox.Text = base.EditingCell.Text;
}
// Sets the contents of the Cell
// being edited based on the value
// in the editor
protected override void SetCellValue()
{
base.EditingCell.Text = this.TextBox.Text;
}
// Starts editing the Cell
public override void StartEditing()
{
this.TextBox.KeyPress +=
new KeyPressEventHandler(OnKeyPress);
this.TextBox.LostFocus +=
new EventHandler(OnLostFocus);
base.StartEditing();
this.TextBox.Focus();
}
// Stops editing the Cell and commits any changes
public override void StopEditing()
{
this.TextBox.KeyPress -=
new KeyPressEventHandler(OnKeyPress);
this.TextBox.LostFocus -=
new EventHandler(OnLostFocus);
base.StopEditing();
}
// Stops editing the Cell and ignores any changes
public override void CancelEditing()
{
this.TextBox.KeyPress -=
new KeyPressEventHandler(OnKeyPress);
this.TextBox.LostFocus -=
new EventHandler(OnLostFocus);
base.CancelEditing();
}
// Gets the TextBox used to edit the Cells contents
public TextBox TextBox
{
get
{
return base.Control as TextBox;
}
}
// Handler for the editors TextBox.KeyPress event
protected virtual void OnKeyPress(object sender,
KeyPressEventArgs e)
{
// check whether we nned to stop or cancel editing
if (e.KeyChar == AsciiChars.CarriageReturn /*Enter*/)
{
if (base.EditingTable != null)
{
base.EditingTable.StopEditing();
}
}
else if (e.KeyChar == AsciiChars.Escape)
{
if (this.EditingTable != null)
{
base.EditingTable.CancelEditing();
}
}
}
// Handler for the editors TextBox.LostFocus event
protected virtual void OnLostFocus(object sender,
EventArgs e)
{
// if the textbox loses focus
// we should stop editing
if (base.EditingTable != null)
{
base.EditingTable.StopEditing();
}
}
}
视觉样式
在 XPTable
中,视觉样式是可继承的——也就是说,Row
s (行) 和 Cell
s (单元格) 将使用其父容器的视觉设置 (除非另有规定)。XPTable
还提供了可以由 Row
s (行) 和 Cell
s (单元格) 共享的样式对象,从而节省系统资源。下图展示了一个此类示例。
CellStyles (单元格样式)
Cell
s (单元格) 有一个 CellStyle
(单元格样式) 属性,该属性允许您在节省系统资源的同时,为多个 Cell
s (单元格) 提供一致的外观和感觉。CellStyle
(单元格样式) 对象提供了四个属性来控制 Cell
(单元格) 的外观:
BackColor
(背景色) - 指定Cell
(单元格) 的背景颜色。ForeColor
(前景颜色) - 指定Cell
(单元格) 的前景色。Font
(字体) - 指定Cell
(单元格) 使用的字体。CellPadding
(单元格内边距) - 指定Cell
(单元格) 边框与其内容之间的空间量。
注意: 在 Cell
(单元格) 上设置这些值中的任何一个都将覆盖从其父 Row
(行) 继承的相同值。Cell
s (单元格) 还有 BackColor
(背景色)、ForeColor
(前景颜色)、Font
(字体) 和 CellPadding
(单元格内边距) 属性,它们使用 CellStyle
(单元格样式) 属性来存储其值。在与其它 Cell
s (单元格) 共享其 CellStyle
(单元格样式) 的 Cell
(单元格) 上设置这些属性中的任何一个都会影响所有其他 Cell
s (单元格)。
RowStyles (行样式)
RowStyle
s (行样式) 与 CellStyle
s (单元格样式) 相同,只是它们由 Row
s (行) 共享,并且没有 CellPadding
(单元格内边距) 属性。
Table styles (表样式)
在此版本中,Table
s (表) 没有 TableStyle
(表样式) 属性 (尽管未来版本会有)。相反,Table
(表) 具有以下属性来控制其外观:
BackColor
(背景色) - 指定Table
(表) 的背景颜色。ForeColor
(前景颜色) - 指定Table
(表) 的前景色。Font
(字体) - 指定Table
(表) 使用的字体。AlternatingRowColor
(交替行颜色) - 指定Table
(表) 的交替行背景色。SelectionBackColor
(选择背景色) - 指定所选Row
s (行) 和Cell
s (单元格) 的背景颜色。SelectionForeColor
(选择前景色) - 指定所选Row
s (行) 和Cell
s (单元格) 的前景色。UnfocusedSelectionBackColor
(非焦点选择背景色) - 指定当Table
(表) 没有焦点时,所选Row
s (行) 和Cell
s (单元格) 的背景颜色。UnfocusedSelectionForeColor
(非焦点选择前景色) - 指定当Table
(表) 没有焦点时,所选Row
s (行) 和Cell
s (单元格) 的前景色。HeaderFont
(表头字体) - 指定用于绘制Column
(列) 标题中文本的字体。GridColor
(网格颜色) - 指定网格线的颜色。GridLineStyle
(网格线样式) - 指定网格线的样式。SortedColumnBackColor
(已排序列背景色) - 指定已排序Column
(列) 的背景颜色。
注意: Row
s (行) 和 Cell
s (单元格) 将继承这些值,除非被显式设置。
下面的示例展示了如何共享 CellStyle
s (单元格样式) 和 RowStyle
s (行样式)。
// create a new CellStyle object
CellStyle cellStyle = new CellStyle();
cellStyle.BackColor = Color.Blue;
cellStyle.ForeColor = Color.Red;
cellStyle.Font = new Font("Tahoma", 8.25f, FontStyle.Bold);
// create a new RowStyle object
RowStyle rowStyle = new RowStyle();
rowStyle.BackColor = Color.Yello;
rowStyle.ForeColor = Color.Green;
rowStyle.Font = new Font("Arial", 8.25f, FontStyle.Italics);
for (int i=0; i<3; i++)
{
tableModel.Rows[i].RowStyle = rowStyle;
// only set the cellstyle for cells in the 3rd column
tableModel[i, 2].CellStyle = cellStyle;
}
排序
表排序是按列进行的,可以通过单击 Column
(列) 的标题或通过代码来启动。
有六种内置的比较器:
ComparerBase
-Cell
(单元格) 比较器的基类。TextComparer
- 用于基于Text
属性比较Cell
s (单元格)。CheckBoxComparer
- 用于基于Checked
属性比较Cell
s (单元格)。NumberComparer
- 用于比较Data
属性中包含数字的Cell
s (单元格)。ImageComparer
- 用于基于Image
属性比较Cell
s (单元格)。ColorComparer
- 用于比较Data
属性中包含Color
s (颜色) 的Cell
s (单元格)。DateTimeComparer
- 用于比较Data
属性中包含DateTime
s (日期时间) 的Cell
s (单元格)。
还有四种内置的排序器:
InsertionSorter (插入排序器)
MergeSorter (归并排序器)
ShellSorter (希尔排序器)
HeapSorter (堆排序器)
InsertionSort 和 MergeSort 被认为是稳定的排序,而 ShellSort 和 HeapSort 是不稳定的。此外,InsertionSort 和 ShellSort 在小列表上比 MergeSort 和 HeapSort 快,在大列表上则慢。实际用于排序 Column
(列) 的算法取决于 Table
(表) 中的 Row
(行) 数量以及是否需要稳定排序。
有关排序方法和稳定/不稳定排序的更多信息,请参阅 此网站。
您可以通过调用 table
的 Sort
方法之一来以编程方式排序 Column
(列)。
// sort the currently sorted column in the opposite direction
// to its currnent sort order, or if no columns are sorted, the
// column that has focus in ascending order
table.Sort();
// sort the currently sorted column in the opposite direction
// to its currnent sort order, or if no columns are sorted, the
// column that has focus in ascending order using an unstable
// sort method
table.Sort(false);
// sort the column at index 3 in the table's ColumnModel
// opposite to its current sort order, or in ascending order
// if the column is not sorted
table.Sort(3);
// sort the column at index 3 in the table's ColumnModel
// opposite to its current sort order, or in ascending order
//if the column is not sorted using a stable sort method
table.Sort(3, true);
// sort the column at index 3 in the table's ColumnModel
// in descending order
table.Sort(3, SortOrder.Descending);
// sort the column at index 3 in the table's ColumnModel
// in ascending order using an unstable sort method
table.Sort(3, SortOrder.Ascending, false);
注意: 不提供稳定或不稳定排序选项的 Sort
方法会自动使用稳定排序。
您可以将 Column
(列) 的 Sortable
属性设置为 false
来禁用 Column
(列) 排序。
// disable sorting for a column
column.Sortable = false;
注意: 将 Table
(表) 的 HeaderStyle
(表头样式) 属性设置为 NonClickable
(不可点击) 或 None
(无) 将阻止通过单击列标题进行列排序,但 Column
(列) 仍然可以以编程方式排序。
创建自定义比较器
还可以通过继承 ComparerBase
(比较器基类) 并重写 Compare
方法来为 Column
(列) 创建自定义比较器。
public class TextComparer : ComparerBase
{
// Compares two objects and returns a
// value indicating whether one is less
// than, equal to or greater than the other
public override int Compare(object a, object b)
{
Cell cell1 = (Cell) a;
Cell cell2 = (Cell) b;
// check for null cells
if (cell1 == null && cell2 == null)
{
return 0;
}
else if (cell1 == null)
{
return -1;
}
else if (cell2 == null)
{
return 1;
}
// check for null data
if (cell1.Text == null && cell2.Text == null)
{
return 0;
}
else if (cell1.Text == null)
{
return -1;
}
// now that we know both cells contain valid data,
// use the frameworks built in string comparer
return cell1.Text.CompareTo(cell2.Text);
}
}
选择
Table
提供了两种可视化选定 Cell
s (单元格) 的方式:Grid
(网格) 样式,其中突出显示单个选定的 Cell
s (单元格);或 ListView
(列表视图) 样式,其中只突出显示第一个可见 Column
(列) 中的 Cell
(单元格)。下图展示了一个示例。
顶部:ListView (列表视图) 样式选择
底部:Grid (网格) 样式选择
可以使用 table
的 SelectionStyle
(选择样式) 属性来设置此选项。
// use grid style selection
table.SelectionStyle = SelectionStyle.Grid;
注意: 在 ListView
(列表视图) 样式选择中,突出显示的 Cell
(单元格) 可能实际上并未被选中。
TableModel
(表模型) 还提供了一个 Selection
(选择) 对象,您可以使用它来以编程方式选择或取消选择 Cell
s (单元格)。
未来功能
下面是我想在未来版本中添加的功能列表:
- 单元格和列标题的自动换行
- 自动调整行高和列宽
- 可变行高
LinkLabel
(链接标签) 单元格- RichTextFormat (富文本格式) 单元格
- 基于对话框的 CellEditors (单元格编辑器)
ListView
(列表视图) 风格的图标模式- RightToLeft (从右到左) 支持
- 剪切和粘贴支持
- 拖放支持
- 数据绑定
- 列重排序
- 打印支持
- 导出到 HTML 和 XML
- 序列化
- 其他我忘记或还没想到的东西
历史
- 2005 年 9 月 11 日 - 初始发布。
- 2005 年 9 月 13 日 - 版本 1.0.1。
- 修复了
Table
(表) 在应用程序最小化时导致崩溃的问题。 - 更新了未来功能列表。
- 修复了
- 2005 年 9 月 17 日 - 版本 1.0.2
- 修复了使用
DropDownCellEditor
(下拉单元格编辑器) 在显示下拉部分时导致崩溃的问题。 - 修复了删除
Row
s (行) 时从TableModel
(表模型) 抛出的异常。 - 修复了
TableModel
s (表模型)/Row
s (行) 在添加/删除Row
/Cell
s (行/单元格) 时未更新Row
/Cell
(行/单元格) 索引,导致绘图问题。 - 修复了
HideSelection
(隐藏选择) 错误,即即使Table
(表) 有焦点,选定的项目也不会显示为选中状态。 - 修复了
Table
(表) 覆盖CellRenderer
(单元格渲染器) 设置的光标。 - 为方便起见,向
Table
(表) 添加了实用方法InvalidateCell
(使单元格无效) 和InvalidateRow
(使行无效)。
- 修复了使用