.NET CF 自定义 DataGrid 格式化
本文将介绍如何在 DataGrid 中自定义单个单元格的格式,并且该方法适用于 Compact Framework。
引言
DataGrid
是 Compact Framework 中一个强大的控件,但要实现对单个单元格的自定义格式化,并控制其“自定义”的原因和方式,并非易事。
本文在 Mazdak 撰写的 这篇文章的基础上进行了扩展,这篇文章几乎实现了我需要的所有功能,但自定义“逻辑”的灵活性还不够。
重要提示
在使用此代码之前,有一些重要的注意事项,其中最重要的是确保安装了正确版本的 .NET Compact Framework。我将非常仔细地说明这一点 - 您需要 .NET CF 版本 2 Service Pack 2。
SP2 部分是关键,因为此版本将 DataGridTextBoxColumn
类的 Paint
事件设置为 virtual
,从而允许我们重写该事件并实现所需的效果。
您可以从 这里获取正确版本的 Framework。
工作原理
我为其中包含的代码所做的贡献微乎其微,因为这种“方法”的许多部分都可以在网上轻易找到。对我(至少对我而言)来说,最困难的部分是将它们整合到一个可重用且灵活的方法中,以提供控件的proper formatting。
基本方法是构建一个继承自 DataGridTextBoxColumn
的类,然后将其应用于网格的表样式。该类包含三个重要元素:一个包含列号的属性,一些(1个或多个)事件,以及对 Paint
事件的重写。
事件是稍微自定义过的;我们使用一个继承自 EventArgs
的简单类,该类允许事件的结果包含行、列和一个布尔值。
基本计划是从 Paint
事件中发出一个事件,等待 DataGridEnableEventArgs
类型的返回结果。我们检查布尔属性(我称之为 meetsCriteria
),然后相应地“绘制”单元格。
下面的代码显示了一个简单版本。CheckCellEven
是我们的事件之一;我们首先检查它是否不为 null
(针对 ColumnStyle
),如果不是,则触发事件。事件返回一个布尔值(基于订阅事件中的某些逻辑),在这种情况下,我们更改 BackBrush
颜色,但我们可以完全访问 graphics canvas,并像在任何其他 Paint
事件中一样绘制线条、字符串等。
protected override void Paint(Graphics g, Rectangle Bounds, CurrencyManager Source,
int RowNum, Brush BackBrush, Brush ForeBrush, bool AlignToRight)
{
if (CheckCellEven != null)
{
DataGridEnableEventArgs e = new DataGridEnableEventArgs
(RowNum, _col, enabled);
CheckCellEven(this, e);
if (e.MeetsCriteria)
BackBrush = new SolidBrush(Color.Orange);
}
base.Paint(g, Bounds, Source, RowNum, BackBrush, ForeBrush, AlignToRight);
}
这是一种简单的实现方式,可以对单个单元格应用多种格式化样式。订阅事件可以位于包含 DataGrid
的同一个类中,因此可以完全访问 DataGrid
本身以及任何其他控件或变量。这使得几乎无限的逻辑可用于确定如何以特定方式绘制每个单元格。
Using the Code
在网格控件用数据填充后(在本例中,数据来自 SDK Northwind 示例),其使用方式与本文无关。
接下来,我们为 DataSet
中的每一列实例化一个 ColumnStyle
类。我包含了几种确定哪些列触发哪些事件订阅的方法,以及几种事件可以确定结果的方法。
请记住,我们的 ColumnStyle
类继承自 DataGridTextBoxColumn
,因此我们将该类的每个实例添加到 DataGridTableStyle
类的实例中,然后再将 DataGridTableStyle
添加到 DataGrid.Tables.Styles
。
我使用了一个匿名方法来连接事件,这值得一看。
在下面的代码中,我们检查 DataTable.Column
并检查其数据类型;如果它是 int
,我们使用匿名方法和 delegate
添加事件处理程序。在这种情况下,我们只检查我们正在绘制的单元格是否包含值 2。
if (dt.Columns[i].DataType == System.Type.GetType("System.Int32"))
myStyle.CheckCellEquals +=
delegate(object sender, DataGridEnableEventArgs e)
{
e.MeetsCriteria = ((int)dataGrid1[e.Row, e.Column] == 2) ?
true : false;
};
并非最终示例
在有人抱怨之前,此示例旨在展示一种我发现难以实现的方法。对发生的任何转换都没有进行错误检查,如果您使用不同的数据,它远非健壮。该方法可以在使用 DataGrid
的任何场景中工作,并且可以进行扩展以构建非常复杂的网格。
不要被下载的大小吓倒,其中主要是 Northwind 数据库,因为我不想花时间填充网格控件,这是最简单的方法。实际代码包含在两个文件中,仅包含三个类和几个方法,实现非常简单。
这只是一个我想要整合起来展示这种方法的简单示例。它将不再进一步开发。
历史
- 2007 年 8 月 29 日:首次发布。