SourceGrid应用/中文文档
SourceGrid 是一个免费的完全以 C# 托管代码编写的 .NET Windows 窗体网格控件. SourceGrid 可用于显示或改变表格形式的数据。
SourceGrid 可用于绑定到一个数据源(以 DataView 为代表),或者直接建立每个单元格。
这种类型的控件有很多可用,但通常需要付费,难于定制或需要面向数据集(DataSet)。
SourceGrid 仅使用托管代码(无API 或 Interop),可以用于任何与 .NET 2 兼容的环境中。
SourceGrid 可用于绑定到一个数据源(以 DataView 为代表),或者直接建立每个单元格。
这种类型的控件有很多可用,但通常需要付费,难于定制或需要面向数据集(DataSet)。
SourceGrid 仅使用托管代码(无API 或 Interop),可以用于任何与 .NET 2 兼容的环境中。
更多的信息,相关的讨论,bug 捕获系统或者需要下载最新的版本,请访问 SourceForge 网页: http://sourceforge.net/projects/sourcegrid ,或者访问我的主页 http://www.devage.com/
要下载控件的最新版,请访问 http://sourceforge.net/projects/sourcegrid. 解压缩该文件后,可参考项目中的这些程序集:
- SourceGrid.dll - SourceGrid 内核库
- DevAge.Core.dll - 共用的辅助功能库
- DevAge.Windows.Forms.dll - Windows 窗体库
- [SourceGrid.Extensions.dll - 可选库,有 SourceGrid 扩展功能(如DataGrid, PlanningGrid)]
- GridVirtual 控件 - 使用虚单元格(ICellVirtual)的网格控件
- Grid 控件 - 使用实体单元格(ICell)的网格控件
典型地,在本文中,我将使用 Grid 控件,因为它更简单,尤其是作为简单的示例。但是,同样的代码基本上也能用于 GridVirtual 控件。
Grid 控件也用作需要最大弹性的那些特殊的网格。
目前,SourceGrid 仅有少量的设计时刻支持,因此通常你必须人工编写代码操作网格。
假定你已经有一个名为 grid1 的 Grid 控件,你可以在 Form.Load 事件中编写如下代码:
grid1.BorderStyle = BorderStyle.FixedSingle;
grid1.ColumnsCount = 3;
grid1.FixedRows = 1;
grid1.Rows.Insert(0);
grid1[0,0] = new SourceGrid.Cells.ColumnHeader("String");
grid1[0,1] = new SourceGrid.Cells.ColumnHeader("DateTime");
grid1[0,2] = new SourceGrid.Cells.ColumnHeader("CheckBox");
for (int r = 1; r < 10; r++)
{
grid1.Rows.Insert(r);
grid1[r,0] = new SourceGrid.Cells.Cell("Hello " + r.ToString(), typeof(string));
grid1[r,1] = new SourceGrid.Cells.Cell(DateTime.Today, typeof(DateTime));
grid1[r,2] = new SourceGrid.Cells.CheckBox(null, true);
}
grid1.AutoSizeCells();
窗体看起就如下图所显示的一样:
- 如果你想读取或改变单元格中的值,可以使用 grid1[r,c].Value 属性, r 和 c 是单元格的行和列。
- 删除某行,可以编写代码如: grid1.Rows.Remove(r)
- 改变列宽,可以编写代码如: grid1.Columns[c].Width = 100
如果你想改变某些单元格的可视属性,你必须使用 View 类。
让我们看看下一个示例:
grid1.BorderStyle = BorderStyle.FixedSingle;
grid1.ColumnsCount = 3;
grid1.FixedRows = 1;
grid1.Rows.Insert(0);
SourceGrid.Cells.Views.ColumnHeader boldHeader = new SourceGrid.Cells.Views.ColumnHeader();
boldHeader.Font = new Font(grid1.Font, FontStyle.Bold | FontStyle.Underline);
SourceGrid.Cells.Views.Cell yellowView = new SourceGrid.Cells.Views.Cell();
yellowView.BackColor = Color.Yellow;
SourceGrid.Cells.Views.CheckBox yellowViewCheck = new SourceGrid.Cells.Views.CheckBox();
yellowViewCheck.BackColor = Color.Yellow;
grid1[0, 0] = new SourceGrid.Cells.ColumnHeader("String");
grid1[0, 0].View = boldHeader;
grid1[0, 1] = new SourceGrid.Cells.ColumnHeader("DateTime");
grid1[0, 1].View = boldHeader;
grid1[0, 2] = new SourceGrid.Cells.ColumnHeader("CheckBox");
grid1[0, 2].View = boldHeader;
for (int r = 1; r < 10; r++)
{
grid1.Rows.Insert(r);
grid1[r, 0] = new SourceGrid.Cells.Cell("Hello " + r.ToString(), typeof(string));
grid1[r, 0].View = yellowView;
grid1[r, 1] = new SourceGrid.Cells.Cell(DateTime.Today, typeof(DateTime));
grid1[r, 1].View = yellowView;
grid1[r, 2] = new SourceGrid.Cells.CheckBox(null, true);
grid1[r, 2].View = yellowViewCheck;
}
我使用 FontStyle.Bold | FontStyle.Underline 建立了一个列标头外观,其中标准单元格的外观为黄色背景,复选框单元格的外观为黄色背景。然后我把它们的实例指派到了每个单元格的 View 属性中。
窗体看起来应该像下图所示的一样:
你可以注意到,我已经为许多单元格指派了 View 类的同一个实例。这对于优化所耗用的系统资源是有用的。
每个单元格可以有一个编辑器(Editor 属性) 相关。编辑器用于编辑单元格的值。你可以人工建立一个编辑类(参阅 SourceGrid.Cells.Editors 命名空间),或者使用 SourceGrid.Cells.Editors.Factory 类建立基于某种类型(Type)的编辑器。如果指定了Type 参数, 你也可以使用 Cell 构造函数自动调用 SourceGrid.Cells.Editors.Factory 。
下面是一个示例,建立一些单元格,并且使用上面所述的某一种方法把单元格与编辑器相关联。
//A DateTime editor
grid1[r, c] = new SourceGrid.Cells.Cell(DateTime.Today, typeof(DateTime));
//A string editor
grid1[r, c] = new SourceGrid.Cells.Cell("Ciao", typeof(string));
//A double editor
grid1[r, c] = new SourceGrid.Cells.Cell(58.4);
grid1[r, c].Editor = SourceGrid.Cells.Editors.Factory.Create(typeof(double));
就像 View 类一样,编辑器也可以在一个或数个单元格之间被共用。
现在,你可以开始使用 SourceGrid 工作了,更进一步的信息请参阅下面的章节。
基础概念 返回目录
Grid 控件
如果你需要最有弹性的, 简易而没有太多单元格的网格, Grid 控件是理想的选择. 事实上, 此控件中每个单元格都作为一个 .NET 类来描述, 因此也占用一定数量的资源. 此外, 这是唯一支持 RowSpan 和 ColumnSpan(单元格合并)功能的网格.
在一个 Windows 窗体中使用此控件是最普通不过的事. 这正如增加其他控件(如按钮, DataGrid)一样. 首先,建立或者打开一个Windows 应用程序项目, 然后从设计器打开一个 Windows 窗体。 现在你要准备好使定制工具箱: 以鼠标右键单击“工具箱 — .NET Framework 组件 — 浏览”,选中“DevAge.SourceGrid.dll”。现在,网格控件被添加到工具箱中,可以像其他控件一样增加到 Windows 窗体中。
在增加控件到窗体后,我们就可以开始编写代码使用网格控件. 例如,在窗体的 Load 事件中,编写如下代码:
grid1.Redim(2, 2);
grid1[0,0] = new SourceGrid.Cells.Cell("Hello from Cell 0,0");
grid1[1,0] = new SourceGrid.Cells.Cell("Hello from Cell 1,0");
grid1[0,1] = new SourceGrid.Cells.Cell("Hello from Cell 0,1");
grid1[1,1] = new SourceGrid.Cells.Cell("Hello from Cell 1,1");
上述代码建立一个 2 行 2 列(Redim 方法) 的表,以单元格装入各个位置。我已经使用了包含实体单元格的 SourceGrid.Cells 命令空间。
可以使用 Value 属性读取特定单元格的值,就像这样: object val = grid1[1,0].Value;.
参阅其它章节了解更多信息。
GridVirtual 控件
当需要显示大量的单元格, 并且已经有可用的结构化数据(例如数据集, 数组, XML文档或其他数据结构)时, 使用 GridVirtual 控件是理想的选择.
除了自动排序(这是因为在复制任何外部数据结构的内容之前, grid 不能进行自动排列), 以及 RowSpan 和 ColumnSpan 这类允许单元格交叉跨越其它邻近单元格的功能(例如合并单元格功能)以外, 这种 GridVirtual 网格控件与 Grid 控件有同样的功能.
另一个缺点是建立虚网格稍显困难.
虚网格主要的概念是, 每个单元格从一个外部的数据结构读取和写入值, 以及网格不持有所有行和列, 而通常是直接从数据源中读取. 此观点以一个抽象的 GridVirtual 类实现, 并且有抽象的方法: CreateRowsObject, CreateColumnsObject 和 GetCell. 你可以使用特定的 IValueModel (接口)直接从数据源中读取值.
因此对于 GridVirtual , 需要建立一个派生于 GridVirtual 的类, 并且定制 CreateRowsObject, CreateColumnsObject 和 GetCell 方法读取数据源是首要的.
GetCell 方法的主要目的是返回一个给定的位置(行或列), 选定的单元格, 以及用于建立列和行对象 CreateRowsObject 和 CreateColumnsObject 方法使用的数据源。这样允许很大的弹性, 因为你可以返回任何 ICellVirtual 给一个特定的类型; 举例来说, 当行号为 0 时, 你可以返回单元格的标头类型.
通常, 你不需要直接使用 GridVirtual , 而是需要使用一个从它派生的控件. 目前, 我已经完成两个可以直接使用虚网格功能的控件:
- DataGrid - 绑定到 DataView 对象的网格.
- ArrayGrid - 绑定到一个 Array 对象的网格
如果你需要建立自定义控件, 从特定数据源读取数据, 你可以参阅 ArrayGrid 类的示例.
单元格概述
每个单元格由 4 个基本部分组成, 它们基于改进的“模式-外观-控制器(Model-View-Controller)”模型:
- 模式(Model): 模式是管理单元格取值的类, 它包含相关的取值或属性, 并且与其他组件相联系.
- 外观(View) : 外观是绘制单元格, 并包含可视属性的类.
- 控制器(Controller) : 控制器是提供单元格行为的类.
- 编辑器(Editor) : 编辑器是定制单元格的编辑器的类.
为了较通用的要求,一些类已经被准备和配置, 但是, 可能会需要以某些代码行建立个性化单元格。 (参阅下一段落了解更多内容)
- Rows - 管理行信息, 基础类是 RowsBase 类.
- Columns - 管理行信息, 基础类是 ColumnsBase 类.
-
grid1.Redim(2,2);
-
grid1.RowsCount = 2; grid1.ColumnsCount = 2;
-
grid1.Rows.Insert(0); grid1.Rows.Insert(1); grid1.Columns.Insert(0); grid1.Columns.Insert(1);
grid1.Rows[0].Height = 100; grid1.Columns[0].Width = 100;
grid1.Redim(2,2); grid1[0, 0] = new SourceGrid.Cells.Cell("Cell 0, 0"); grid1[1, 0] = new SourceGrid.Cells.Cell("Cell 1, 0"); grid1[0, 1] = new SourceGrid.Cells.Cell("Cell 0, 1"); grid1[1, 1] = new SourceGrid.Cells.Cell("Cell 1, 1");
- 在值只需要被存储在原始数据源的情况下, 执行虚网格。 在此情况下, 如果以正确的方式选择模式, 可以从数据源直接地读取数据。
- 需要扩充单元格类, 但是维持代码的易于重用性。 这是因为你不一定要改变基本的单元格类(Cell class)来增加新的功能,而是可以只增加一个新的模式。
- IValueModel
- IToolTipText
- ICheckBox
- ISortableHeader
- SourceGrid.Cells.Views.Cell - 用于标准的单元格, 在此种外观下, 可以定制颜色, 字体, 边框和许多属性.
- SourceGrid.Cells.Views.Button - 用于按钮风格的单元格, 有主题(theme)支持.
- SourceGrid.Cells.Views.Link - 用于链接风格的单元格.
- SourceGrid.Cells.Views.CheckBox* - 用于复选框类型的单元格. 复选框可被选中, 禁止和包含标题文本.
- SourceGrid.Cells.Views.Header* - 用于一般的标头单元格.
- SourceGrid.Cells.Views.ColumnHeader* - 用于列标头单元格, 有主题(theme)支持.
- SourceGrid.Cells.Views.RowHeader - 用于行标头单元格, 有主题(theme)支持
- SourceGrid.Cells.Views.MultiImages - 允许在单元格中绘制多个图像.
SourceGrid.Cells.Views.Cell view = new SourceGrid.Cells.Views.Cell(); view.BackColor = Color.Khaki; grid1[0,0].View = view; grid1[2,0].View = view;
public class MyView : SourceGrid.Cells.Views.Cell { protected override void DrawCell_Background(SourceGrid.Cells.ICellVirtual p_Cell, SourceGrid.Position p_CellPosition, PaintEventArgs e, Rectangle p_ClientRectangle) { base.DrawCell_Background (p_Cell, p_CellPosition, e, p_ClientRectangle); e.Graphics.DrawEllipse(Pens.Red, p_ClientRectangle); } }
MyView myView = new MyView(); //...... code to populate the grid grid1[r, c].View = myView;
- SourceGrid.Cells.Controllers.Cell - 单元格的共有行为.
- SourceGrid.Cells.Controllers.Button - 单元格作为按钮.
- SourceGrid.Cells.Controllers.CheckBox* - 单元格有复选框行为(需要 ICheckBox 模式)
- SourceGrid.Cells.Controllers.ColumnFocus - 当单击标头单元格时, 用于设置列的焦点.
- SourceGrid.Cells.Controllers.ColumnSelector - 当单击标头单元格时, 用于选中列.
- SourceGrid.Cells.Controllers.CustomEvents - 用于触发一系列事件, 而无须建立新的控制器
- SourceGrid.Cells.Controllers.FullColumnSelection - 用于允许列选区模式.
- SourceGrid.Cells.Controllers.FullRowSelection - 用于允许行选区模式.
- SourceGrid.Cells.Controllers.MouseCursor - 用于显示在单元格上的鼠标指针.
- SourceGrid.Cells.Controllers.MouseInvalidate - 当接收到一个鼠标事件时, 用于使用单元格区失效.
- SourceGrid.Cells.Controllers.Resizable - 用于建立可调整大小(宽度和高度)的单元格.
- SourceGrid.Cells.Controllers.RowFocus - 当单击标头单元格时, 用于设置行的焦点.
- SourceGrid.Cells.Controllers.RowSelector - 当单击标头单元格时, 用于选中行.
- SourceGrid.Cells.Controllers.SortableHeader* - 用于建立可排序的列标头单元格(需要 ISortableHeader 模式)
- SourceGrid.Cells.Controllers.ToolTipText* - 用于建立带提示条的单元格(需要 IToolTipText 模式)
- SourceGrid.Cells.Controllers.Unselectable - 用于建立不可选的单元格.
下面是可用于控制器内部的事件:
- 鼠标事件: OnMouseDown, OnMouseUp, OnMouseMove, OnMouseEnter, OnMouseLeave
- 键盘事件: OnKeyUp, OnKeyDown, OnKeyPress
- 点击事件: OnDoubleClick, OnClick
- 焦点事件: OnFocusLeaving, OnFocusLeft, OnFocusEntering, OnFocusEntered, CanReceiveFocus
- 单元格取值事件: OnValueChanging, OnValueChanged
- 编辑事件: OnEditStarting, OnEditStarted, OnEditEnded
编写一些代码行,你可以建立定制的控制器(custom Controller),在此情况下,建议类从已经拥有某些默认方法的 ControllerBase 派生。 在下列示例中,当用户在单元格之上移动鼠标时,建立一个改变单元格背景色的一个控制器:
public class MyController : SourceGrid.Cells.Controllers.ControllerBase
{
private SourceGrid.Cells.Views.Cell MouseEnterView = new SourceGrid.Cells.Views.Cell();
private SourceGrid.Cells.Views.Cell MouseLeaveView = new SourceGrid.Cells.Views.Cell();
public MyController()
{
MouseEnterView.BackColor = Color.Green;
}
public override void OnMouseEnter(SourceGrid.CellContext sender, EventArgs e)
{
base.OnMouseEnter (sender, e);
sender.Cell.View = MouseEnterView;
sender.Grid.InvalidateCell(sender.Position);
}
public override void OnMouseLeave(SourceGrid.CellContext sender, EventArgs e)
{
base.OnMouseLeave (sender, e);
sender.Cell.View = MouseLeaveView;
sender.Grid.InvalidateCell(sender.Position);
}
}
MyController myController = new MyController(); //...... code to populate the grid grid1[r, c].AddController(myController);
grid1.Controller.AddController(new MyController());
class ClickController : SourceGrid.Cells.Controllers.ControllerBase { public override void OnClick(SourceGrid.CellContext sender, EventArgs e) { base.OnClick(sender, e); object val = sender.Value; if (val != null) MessageBox.Show(sender.Grid, val.ToString()); } }
grid1.Controller.AddController(new ClickController());
public class ValueChangedEvent : SourceGrid.Cells.Controllers.ControllerBase { public override void OnValueChanged(SourceGrid.CellContext sender, EventArgs e) { base.OnValueChanged(sender, e); string val = "Value of cell {0} is '{1}'"; MessageBox.Show(sender.Grid, string.Format(val, sender.Position, sender.Value)); } }
grid1.Controller.AddController(new ValueChangedEvent());
- ComboBox - 组合框编辑器.
- DateTimePicker - 日期时间选择编辑器
- NumericUpDown - NumericUpDown 编辑.
- TextBox - 文本框编辑. 这是比较常用的编辑器, 可被所有支持字符串转换的类型调用(string, int, double, enum,....).
- TextBoxCurrency - 数值货币专用的文本框编辑器
- TextBoxNumeric - 数值数据专用的文本框编辑器 .
- TimePicker - 时间值专用的 DateTimePicker 编辑器.
- TextBoxUITypeEditor - 提供给拥有 UITypeEditor 的全部类型单元格使用. 这是一个非常有用的类, 因为许多类型都支持该类: DateTime, Font, enums, 也可以建立自定义的 UITypeEditor.
- ImagePicker - 一个可用于选择图像文件并且编辑 byte[] 值的编辑器
- 建立指定值类型的单元格. 这样, 单元格自动调用功能函数 SourceGrid.Cells.Editor.Factory.Create, 为指定类型或 null 返回一个有效的编辑器(Editor).
//String cell grid1[0, 0] = new SourceGrid.Cells.Cell("Hello", typeof(string)); //Double cell grid1[0, 1] = new SourceGrid.Cells.Cell(0.7, typeof(double));
- 分别建立编辑器(Editor), 然后把它指派到单元格:
//String editor SourceGrid.Cells.Editors.IEditor editorString = SourceGrid.Cells.Editor.Factory.Create(typeof(string)); //Double editor SourceGrid.Cells.Editors.IEditor editorDouble = SourceGrid.Cells.Editor.Factory.Create(typeof(double)); //String cell grid1[0, 0] = new SourceGrid.Cells.Cell("Hello"); grid1[0, 0].Editor = editorString; //Double cell grid1[0, 1] = new SourceGrid.Cells.Cell(0.7); grid1[0, 1].Editor = editorDouble;
当你需要为多个单元格使用相同的编辑器时, 推荐使用此方法。 - 人工建立适当的编辑器, 然后把它指派到单元格:
SourceGrid.Cells.Editors.TextBox txtBox = new SourceGrid.Cells.Editors.TextBox(typeof(string)); grid1[2,0].Editor = txtBox;
举例来说明在此种情况下,人工建立类 EditorTextBox , 然后设置属性 MaxLength.
//String 型编辑器 SourceGrid.Cells.Editors.TextBox editorString = new SourceGrid.Cells.Editors.TextBox(typeof(string)); editorString.Control.MaxLength = 10; //字符串单元格 grid1[0, 0] = new SourceGrid.Cells.Cell("Hello"); grid1[0, 0].Editor = editorString;
编辑器也可以被用作定制单元格的格式, 在下面的代码中举例来说明(使用一种定制的数值格式):
//Double 型编辑器
SourceGrid.Cells.Editors.TextBoxNumeric editorDouble = new SourceGrid.Cells.Editors.TextBoxNumeric(typeof(double));
editorDouble.TypeConverter = new DevAge.ComponentModel.Converter.NumberTypeConverter(typeof(double), "#,###.00");
//字符串单元格
grid1[0, 0] = new SourceGrid.Cells.Cell(9419.3894);
grid1[0, 0].Editor = editorDouble;
- DevAge.ComponentModel.Converter.NumberTypeConverter - 用于数值型, 如: double, decimal, int, float
- DevAge.ComponentModel.Converter.PercentTypeConverter - 用于以百分比格式表示的数值型, 如: double, decimal 和 float.
- DevAge.ComponentModel.Converter.CurrencyTypeConverter - 用于以货币格式表示的 Decimal 和 double 类型.
- DevAge.ComponentModel.Converter.DateTimeTypeConverter - DateTime 类型.
下面是建立定制格式的 DateTime 编辑器的另一个实例:
//有定制格式的 DateTime 编辑器
string[] dtParseFormats = new string[] { dtFormat2 };
System.Globalization.DateTimeStyles dtStyles = System.Globalization.DateTimeStyles.AllowInnerWhite |
System.Globalization.DateTimeStyles.AllowLeadingWhite |
System.Globalization.DateTimeStyles.AllowTrailingWhite |
System.Globalization.DateTimeStyles.AllowWhiteSpaces;
TypeConverter dtConverter = new DevAge.ComponentModel.Converter.DateTimeTypeConverter(dtFormat2, dtParseFormats, dtStyles);
SourceGrid.Cells.Editors.TextBoxUITypeEditor editorDt2 = new SourceGrid.Cells.Editors.TextBoxUITypeEditor(typeof(DateTime));
editorDt2.TypeConverter = dtConverter;
grid[currentRow, 1] = new SourceGrid.Cells.Cell(DateTime.Today);
grid[currentRow, 1].Editor = editorDt2;
下图表示大部份可用的编辑器和一些特定单元格(图片从例 3 取得):
以用户控件或特定行为的少量代码行, 来建立一个定制的编辑器(Editor)是可行的。
你可以从 EditorControlBase 派生自定义类, 并建立任何 Windows 窗体控件。下面是使用 DateTimePicker 控件的一个编辑器的示例:
public class DateTimePicker : EditorControlBase
{
public DateTimePicker():base(typeof(System.DateTime))
{
}
protected override Control CreateControl()
{
System.Windows.Forms.DateTimePicker dtPicker =
new System.Windows.Forms.DateTimePicker();
dtPicker.Format = DateTimePickerFormat.Short;
dtPicker.ShowCheckBox = AllowNull;
return dtPicker;
}
protected override void OnChanged(EventArgs e)
{
base.OnChanged(e);
if (Control != null)
Control.ShowCheckBox = AllowNull;
}
public new System.Windows.Forms.DateTimePicker Control
{
get
{
return (System.Windows.Forms.DateTimePicker)base.Control;
}
}
protected override void OnStartingEdit(CellContext cellContext,
Control editorControl)
{
base.OnStartingEdit(cellContext, editorControl);
System.Windows.Forms.DateTimePicker dtPicker =
(System.Windows.Forms.DateTimePicker)editorControl;
dtPicker.Font = cellContext.Cell.View.Font;
}
public override void SetEditValue(object editValue)
{
if (editValue is DateTime)
Control.Value = (DateTime)editValue;
else if (editValue == null)
Control.Checked = false;
else
throw new SourceGridException
("Invalid edit value, expected DateTime");
}
public override object GetEditedValue()
{
if (Control.Checked)
return Control.Value;
else
return null;
}
protected override void OnSendCharToEditor(char key)
{
}
}
因为每个编辑器只与一个 Windows 窗体控件相关(因此它是非常繁重的?), 所以对于大型网格,共用编辑器总是一个好主意.
-
SourceGrid.Cells.Virtual —— 此命名空间包含可以与 GridVirtual 控件一起使用的所有的虚单元格。
- CellVirtual - 基本单元格;用于大部分常规的虚单元格类型.
- Header - 标头单元格.
- ColumnHeader - 列头单元格.
- RowHeader - 行头单元格.
- Button - 按钮单元格.
- CheckBox - 复选框单元格.
- ComboBox - 组合框单元格
- Link - 链接风格的单元格.
- Image - 图象单元格.
- SourceGrid.Cells —— 此命名空间包含可以与 Grid 控件一起使用的所有的实体单元格.
- Cell - 所有其他类型的基本单元格, 用于最普通类型的实体单元格。
- Header - 标头单元格.
- ColumnHeader - 列头单元格.
- RowHeader - 行头单元格.
- Button - 按钮单元格.
- CheckBox - 复选框单元格.
- ComboBox - 组合框单元格.
- Link - 链接风格的单元格.
- Image - 图象单元格.
举例来说,SourceGrid.Cells.CheckBox 单元格的代码如下:
public class CheckBox : Cell
{
public CheckBox(string caption, bool checkValue):base(checkValue)
{
if (caption != null && caption.Length > 0)
View = Views.CheckBox.MiddleLeftAlign;
else
View = Views.CheckBox.Default;
Model.AddModel(new Models.CheckBox());
AddController(Controllers.CheckBox.Default);
AddController(Controllers.MouseInvalidate.Default);
Editor = new Editors.EditorBase(typeof(bool));
Caption = caption;
}
private Models.CheckBox CheckBoxModel
{
get{return (Models.CheckBox)Model.FindModel(typeof(Models.CheckBox));}
}
public bool Checked
{
get{return CheckBoxModel.GetCheckBoxStatus(this, Range.Start).Checked;}
set{CheckBoxModel.SetCheckedValue(this, Range.Start, value);}
}
public string Caption
{
get{return CheckBoxModel.Caption;}
set{CheckBoxModel.Caption = value;}
}
}
取得焦点的单元格接收所有的鼠标和键盘事件, 选中单元格可以接收复制、粘贴和清除的操作。
最重要的方法是:
- StartEdit/EndEdit —— 在特定的单元格上开始/停止编辑
- DisplayText —— 返回单元格的文本(string)
- Value —— 返回单元格的值(object)
SourceGrid.CellContext context = new SourceGrid.CellContext(grid, new SourceGrid.Position(r, c)); context.Value = "hello"; context.StartEdit();
下面是一个改变单元格边框的示例:
DevAge.Drawing.Border border = new DevAge.Drawing.Border(Color.Red, 1);
DevAge.Drawing.RectangleBorder cellBorder = new DevAge.Drawing.RectangleBorder(border, border);
SourceGrid.Cells.Views.Cell view = new SourceGrid.Cells.Views.Cell();
view.Border = cellBorder;
grid[r, c].View = view;
你可以在每个单元格上绑定一个提示条(ToolTip). 必须建立一个SourceGrid.Cells.Controllers.ToolTipText 控制器 , 并把它关联到单元格中.示例如下:
SourceGrid.Cells.Controllers.ToolTipText toolTipController = new SourceGrid.Cells.Controllers.ToolTipText();
toolTipController.ToolTipTitle = "ToolTip example";
toolTipController.ToolTipIcon = ToolTipIcon.Info;
toolTipController.IsBalloon = true;
grid1[r, c] = new SourceGrid.Cells.Cell("Hello");
grid1[r, c].ToolTipText = "Example of tooltip, bla bla bla ....";
grid1[r, c].AddController(toolTipController);
单元格的 ToolTipText 属性自动把一个 SourceGrid.Cells.Models.IToolTipText 接口绑定到标准单元格上.
使用下列代码, 你可以为单元格建立一个上下文菜单(快捷菜单) . 首先以 ContextMenu 定义一个 控制器(controller) :
//以 ContextMenu 定义一个 controller
public class PopupMenu : SourceGrid.Cells.Controllers.ControllerBase
{
ContextMenu menu = new ContextMenu();
public PopupMenu()
{
menu.MenuItems.Add("Menu 1", new EventHandler(Menu1_Click));
menu.MenuItems.Add("Menu 2", new EventHandler(Menu2_Click));
}
public override void OnMouseUp(SourceGrid.CellContext sender, MouseEventArgs e)
{
base.OnMouseUp (sender, e);
if (e.Button == MouseButtons.Right)
menu.Show(sender.Grid, new Point(e.X, e.Y));
}
private void Menu1_Click(object sender, EventArgs e)
{
//TODO Your code here
}
private void Menu2_Click(object sender, EventArgs e)
{
//TODO Your code here
}
}
PopupMenu menuController = new PopupMenu(); ... grid1[r, c] = new SourceGrid.Cells.Cell("Hello"); grid1[r, c].AddController(menuController);
grid1.ClipboardMode = SourceGrid.ClipboardMode.All;
如果你需要定制某些单元格的外观, 建议建立一个新类, 并在此类编写定制代码. 以这种习惯, 你可以在所有应用程序和窗体中重用类. 举例来说, 假如你需要指定所有单元格的背景色为灰色, 可以新建下面的类:
public class GrayView : SourceGrid.Cells.Views.Cell
{
public new static readonly GrayView Default = new GrayView();
public GrayView()
{
BackColor = Color.LightGray;
}
}
public class GrayCell : SourceGrid.Cells.Cell
{
public GrayCell(object val):base(val)
{
View = GrayView.Default;
}
}
SourceGrid.Cells.Button bt = new SourceGrid.Cells.Button();
using Cells = SourceGrid.Cells; ................. Cells.Button bt = new Cells.Button();
BoundListBase 是一个抽象类, 可用于作为通用层, 绑定任何类型的列表控件到数据源.
典型的数据源是 System.Data.DataView 或一个自定义列表类.目前有 2 种使用 BoundListBase 的类:
- DevAge.ComponentModel.BoundDataView —— 用于 System.Data.DataView.
- DevAge.ComponentModel.BoundList<T> —— 用于任何 List<T> 类. 你可以使用任何类型的有默认构造函数和公用属性的对象.
基本上, DataGrid 控件使用一个类型为 IValueModel 的特殊 Model 类, 直接从数据源中读取数据。 SourceGrid.DataGrid 有一个 DataSource 属性用于存储 BoundListBase 对象. 下面是如何使用该控件的一个简单示例:
//建立实例 DataTable
DataTable table = new DataTable();
table.Columns.Add("A", typeof(string));
table.Columns.Add("B", typeof(bool));
table.Rows.Add(new object[]{"Row 1", false});
table.Rows.Add(new object[]{"Row 2", true});
table.Rows.Add(new object[]{"Row 3", false});
dataGrid1.DataSource = new DevAge.ComponentModel.BoundDataView(table.DefaultView);
在上面的代码中, 我已经建立一个 2 列 n 行的 DataTable , 接下来你可以使用 DefaultView 属性取一个 DataView 类, 并通过建立一个 BoundDataView 类的实例指派到 DataGrid 控件. 如果你需要可定制的列, 可使用 Columns 属性. 该属性返回一个DataGridColumn 对象的集合, 你可以自定义每列来建立定制单元格.下面是实例:
//建立一个自定义 View 类
SourceGrid.Cells.Views.Cell view = new SourceGrid.Cells.Views.Cell();
view.BackColor = Color.LightBlue;
//人工添加列
SourceGrid.DataGridColumn gridColumn;
gridColumn = dataGrid.Columns.Add("Country", "Country", typeof(string));
gridColumn.DataCell.View = view;
SourceGrid.Conditions.ICondition condition = SourceGrid.Conditions.ConditionBuilder.AlternateView(gridColumn.DataCell.View, Color.LightGray, Color.Black); gridColumn.Conditions.Add(condition);
在下面其他示例中, 我建立一些条件, 当特定列为 true 时实现粗体绿色前景的外观.
SourceGrid.Conditions.ConditionView selectedConditionBold =
new SourceGrid.Conditions.ConditionView(viewSelected);
selectedConditionBold.EvaluateFunction = delegate(SourceGrid.DataGridColumn column,
int gridRow, object itemRow)
{
DataRowView row = (DataRowView)itemRow;
return row["Selected"] is bool && (bool)row["Selected"] == true;
};
gridColumn.Conditions.Add(selectedConditionBold);
- DevAge.Core.dll, DevAge.Windows.Forms.dll —— 一个有许多功能的开源 .NET 库, 包含绘图库的内核, 以及某些用于编辑器的控件. 你可以在DevAgeSourcePack 文章 中找到这些库文件.
- 提高性能.
- 支持其他平台: PocketPC, Mono, ...
- 更好地支持 Windows 窗体设计和其他所见即所得功能