SourceGrid 2.0
下载来源和二进 - 825 KbDownload Source and Binary - 825 Kb
下载文件编写 - 1.35 MBDownload Documentation - 1.35 MB
官方的 SourceGrid 网站Official SourceGrid Website
l 介绍
l 使用 SourceGrid
1. 工程和配置
2. SourceGridMini (精简版的。NET Framework支持)
3. Controls
4. Grid
5. GridVirtual
l VisualModel
l DataModel
l BehaviorModel
l Cells(单元格)
l Grid的结构
1. 列和行
2. panels 面板
l 事件
l ContextMenu(上下文菜单)
l 焦点和选择
l 位置和范围
l 性能
l 扩展
l Screenshots(屏幕截图)
l 如何使用
l 功能
l 重新写您的 SourceGrid 代码
l 未来发展
l 已知的问题
l 早先的版本
l 历史
l 许可
介绍:
SourceGrid 是一个的完全地用C#开发的Windows窗体控件;我的目标是产生一个简单的但是灵活的(网格)grid,每当使改变一个表格式的一系列的数据时必需是可见的。(注:显示数据的需求)
有许多这系列的控件可以用, 但是时常是贵的(收注册费等), 很难符合客户需求,或者不是和.NET一致的(注:不受.NETframework支持)
微软公司 DataGrid 不容易根据客户的需求定制(相信和我一样很多人遇到同样的问题了),当他的数据源不是DataSet时通常显得比较复杂,难使用!
我想要谢谢 Chirs Beckett, Anthony Berglas, Wayne Tanner, Ernesto Perales, Vadim Katsman, Jeffery Bell, Gmonkey, cmwalolo, Kenedy, zeromus, Darko Damjanovic, John Pierre, Achim Schäfer, Michael Look, Elmü (http://kickme.to/elmue) 和帮我解决了编码,Bug和给我新的主意和提议的许多其他的人。
在此对我已经用产生 CHM 帮忙的 NDoc 的表示特别谢谢。
这个控件与微软公司的Microsoft Framework. NET 1.1一起编译。并且引用SourceLibrary.dll 1.2.3.1, 这是个通常的功能集的一个小的库。 我在ZIP 文件里介绍了的这一个动态链接库, 但是最好下载来自位置 http:// www.devage.com/. 的整个源码和最近的版本dll;使用条件:Visual Studio .NET 2003 或其它兼容的开发环境。。
最新版的控件从 http:// www.devage.com/.下载
如果你有问题,可以给我发邮件:webmaster@devage.com
在这篇文章中我想要介绍SourceGrid的概观和其功能性。
因为关于类,特性或方法的细节你能以 CHM 的格式帮助文件里获取 或 ZIP 文件的示例工程。
使用 SourceGrid
工程和配置
在附上的文件中有 4个工程:
l SourceGrid(SourceGrid2.dll)- .NET Framework下的主工程
l SampleProject- .NET Framework下的示例工程
l SourceGridMini(SourceGridMini.dll)-精简版类库下的SourceGrid(例如:PocketPC中使用该控件)
l SampleProjectMini-精简版类库下的SourceGrid 示例
我已经建立 2 解决方案:
SourceGrid2.sln
标准的版本Framework
SourceGrid2Mini.sln
精简版Framework
SourceGridMini 精简版Framework支持
SourceGridMini 是 SourceGrid 版本为精简结构。 这一个版本使用与正常的版本相同——除了由于一些条件下的代码不被支持 (即:精简版类库不支持)
例如: 一些鼠标事件 (MouseEnter , MouseLeave,.。.)
对于 SourceGridMini 仍然有许多工作要完成,我一定将图画最佳化方法并且进行必需的检查并且测试许多功能最终产生稳定的工作版本。
我已经以Microsoft Pocket PC 2003 Emulator作为测试平台。
当你最初打开一个解决方案的时候(即:示例解决方案),将有一个错误,找不到SourceLibraryMini.dll,这是个引用问题……
要解决这个问题,你所要做的是首先删除未找到的SourceLibraryMini.dll,接着找到SourceLibraryMini.dll的物理位置,再重新添加一次引用。
从现在开始文章涉及.NET Framework,但是大多数的代码和一些解释是针对精简版类库的,,未来我将会试着区别二个版本。
控件
SourceGrid2.dll有里面的 2 控件能在VS.NET的工具箱中被插入,且在任何窗体中被使用:
GridVirtual
一个虚拟单元格组成的网格
Grid
- 一个真正的单元格组成网格.
因此那里是二个基本上清楚的物件: 虚拟表格和真实表格。
虚拟的表格是决定外表和单元格的行为但是不包含数值。
真正的表格有如同虚拟表格一般的特性但是也包含表格的数值, 而且因此被关联到到网格的一个特定的位置。
每个单元格由三个基本部份组成:
DataModel
: DataModel 是处理单元格的数值的类。它将单元格的数值转换成一个字串使其可视化,产生单元格的编辑、验证插入的值等操作。
VisualModel
: VisualModel绘制单元格的类,包含可视的属性
BehaviorModel
: BehaviorModel 是提供单元格的行为的类。
这一个细分允许很棒的弹性代码的再可用性, 节省时间而且为每一用户定制的类型提供坚实的基础。。
通常的说,现在已经有一些类安排而且配置好, 你只需要使用很少的一些程序编码就有可能产生符合你要求的个人化的单元格。 (为明细见到下一个段落)
网格(Grid)
如果你想要最好的弹性和简单性,网格(Grid)控件是最理想的除了没有许多单元格之外。事实上,在这控件中,每个单元格都被表现被一个类来表示,并且因此占领一个资源的特定量。 而且这是唯一的支持 RowSpan 和 ColumnSpan 的功能网格(Grid).(单元格合并)
在窗体中插入控件之后,我们就能马上开始写我们的使用网格(Grid)的编码了。
举例来说在窗体的加载事件中我们能写这样的代码:
grid1.Redim(2, 2);
grid1[0,0] = new SourceGrid2.Cells.Real.Cell("Hello from Cell 0,0");
grid1[1,0] = new SourceGrid2.Cells.Real.Cell("Hello from Cell 1,0");
grid1[0,1] = new SourceGrid2.Cells.Real.Cell("Hello from Cell 0,1");
grid1[1,1] = new SourceGrid2.Cells.Real.Cell("Hello from Cell 1,1");
第一行代码用 2个行和 2个列产生一个表而且用一个单元格放置在每个位置。 我已经使用 SourceGrid2.Cells.Real
名称空间,它包含了真正的单元格的定义。
每个单元格包含了所有的必需的显示属性
举例来说;包含改变单元格背景颜色:(由我们自定义)
SourceGrid2.Cells.Real.Cell l_Cell = new SourceGrid2.Cells.Real.Cell("Custom back color");
l_Cell.BackColor = Color.LightGreen;
这些是单元格的主要视觉特性:(对于一个整个的列表请教网格(Grid)的文档) :BackColor, ForeColor, Border, Font, TextAlignment, WordWrap ...
,
现在我们试着创建整个的网格(Grid),有表头、自动排序、根据鼠标或者字符串调整列的宽度,并且有日期和一个选择框
grid1.BorderStyle = BorderStyle.FixedSingle;
grid1.ColumnsCount = 3;
grid1.FixedRows = 1;
grid1.Rows.Insert(0);
grid1[0,0] = new SourceGrid2.Cells.Real.ColumnHeader("String");
grid1[0,1] = new SourceGrid2.Cells.Real.ColumnHeader("DateTime");
grid1[0,2] = new SourceGrid2.Cells.Real.ColumnHeader("CheckBox");
for (int r = 1; r < 10; r++)
{
grid1.Rows.Insert(r);
grid1[r,0] = new SourceGrid2.Cells.Real.Cell("Hello " + r.ToString(), typeof(string));
grid1[r,1] = new SourceGrid2.Cells.Real.Cell(DateTime.Today, typeof(DateTime));
grid1[r,2] = new SourceGrid2.Cells.Real.CheckBox(true);
}
grid1.AutoSizeAll();
在前面的码中我已经设定了网格(Grid)边缘,列的数目,固定行的数目而且创造了第一个表头行。 对于表头我已经用一个 ColumnHeader 单元格。 藉由一个简单的循环我已经建立使用不同类型的每个列的其他单元格。单元格类别自动地为被指定。 ( 在这情况下即一个本文框和 DateTimePicker) 对于最后一个列我已经用一个在单元格中直接地允许勾选栏显示的勾选栏单元格。
窗体应该看起来像下列的截图那个一样。 这一个例子在 ZIP 文件的工程 SampleProject 中也是有的。
你可以使用这样的语句获取单元格的值:object val = grid1[1,0].Value;
.
GridVirtual
当需要用许多地单元格将一些数据呈现出来的时候, GridVirtual 控件是理想的;通常你已经有可得的结构化的数据,像DataSet、一个数据组的数据,一个行列,一个XML文件或其他的数据结构。
网格(Grid)控件除了自动的排序 ( 这因为网格(Grid)没有拷贝不能够自动地排序任何的外部数据结构的内容) 单元格合并,允许生成的单元格跨越相邻的单元格
(汗:英语水平太烂,此处翻译感觉不行……)
另外的缺点是创造一个虚拟的网格(Grid)稍微更困难。
一个虚拟的网格(Grid)主要的观念是单元格不包含数值, 但是读写来自一个外部的数据结构的数值。 这一个思想和抽象的类别 CellVirtual 一起,它必需重新实现定义的方法 GetValue 和 SetValue 。
使用它因此是必需产生一个衍生于 CellVirtual 的类,并且自定义读取数据源的数据;
它也通常是比较好产生于 GridVirtual ,而且为了要有比较棒的弹性和较多的固定代码 , 重载方法 GetCell 的控件。
如果你偏爱你能直接地使用 GridVirtual 控件并且使用事件 GettingCell 。 方法 GetCell 的目的或事件 GettingCell 对于一个给定的位置 (列和栏) 是返回被选择的单元格。 因为你能为一个特定的类型返回任何的 ICellVirtual ,所以这允许很棒的弹性;
当列是 0 的时候,举例来说你可以返回一个类型表头的单元格。
在下列的例子中我已经建立一个读写由数组存储数值的虚拟的网格(Grid)。 首先我已经在窗体中插入控件 GridVirtual,。然后我再写定义虚拟的类继承从 CellVirtual :
public class CellStringArray : SourceGrid2.Cells.Virtual.CellVirtual
{
private string[,] m_Array;
public CellStringArray(string[,] p_Array):base(typeof(string))
{
m_Array = p_Array;
}
public override object GetValue(SourceGrid2.Position p_Position)
{
return m_Array[p_Position.Row, p_Position.Column];
}
public override void SetValue(SourceGrid2.Position p_Position, object p_Value)
{
m_Array[p_Position.Row, p_Position.Column] = (string)p_Value;
OnValueChanged(new SourceGrid2.PositionEventArgs(p_Position, this));
}
}
在早先的码中我已经创建了一个虚拟单元格,读写存储在数组里的值,当调用SetValue方法之后,我们接着调用OnValueChanged方法提醒grid更新这个单元格。
在窗体的加载事件中我插入这一个代码:
private void frmSample15_Load(object sender, System.EventArgs e)
{
gridVirtual1.GettingCell += new SourceGrid2.PositionEventHandler(gridVirtual1_GettingCell);
gridVirtual1.Redim(1000,1000);
string[,] l_Array = new string[gridVirtual1.RowsCount, gridVirtual1.ColumnsCount];
m_CellStringArray = new CellStringArray(l_Array);
m_CellStringArray.BindToGrid(gridVirtual1);
}
我已经把一个事件处理程式加入 GettingCell 事件,又由1000个列和 1000个栏建立网格(Grid)和数组, 建立先前定义的虚拟单元格的一个新实例 CellStringArray ,而且由方法 BindToGrid 我已经把单元格和网格(Grid)相连。
我已经建立一个单一虚拟的单元格, m_CellStringArray,那将会作为点阵式的每个位置。 我们总是必需调用在我们想要在一个虚拟的网格(Grid)中使用的单元格上的方法 BindToGrid 。
为了要完成这个程序,我们应该为单元格写方法 GettingCell 而且储存变数:
private CellStringArray m_CellStringArray;
private void gridVirtual1_GettingCell(object sender, SourceGrid2.PositionEventArgs e)
{
e.Cell = m_CellStringArray;
}
结果应该看起来像下列的图片那一个一样。 这一个例子也在被包含在 ZIP 文件之中的工程 SampleProject 中。
VisualModel
Namespace: SourceGrid2.VisualModels
每个单元格有VisualModel
属性,返回一个类型IVisualModel
的接口。
单元格使用这一个接口绘图并且使单元格的视觉特性符合客户需求。
VisualModel
的目的是将绘图和其它部分的代码分离并且允许在单元格之间的相同视觉的模型共享。 事实上 VisualModel
的相同实例同时地能在许多单元格上被用,这将系统的资源使用最佳化。
然而, 默认的 VisualModel
类是只读的,每 VisualModel
具有一个允许你产生相同的模型同一实例的复制方法。
以下是默认的 VisualModel
在名称空间SourceGrid2.VisualModels
下的类别:
SourceGrid2.VisualModels.Common
:
能自定义颜色,字型,边缘
SourceGrid2.VisualModels.CheckBox
*:
为勾选栏用设计单元格。 勾选栏能被选择, 设置为无效而且能包含一个说明。
SourceGrid2.VisualModels.Header
*:
为表头用以 3D立体边缘设计单元格。
SourceGrid2.VisualModels.MultiImages
:
允许单元格的超过一个图像的图画。
-
*与一个星号一起作记号的 VisualModel 需要一个特别的接口才能正确地工作,
举例来说勾选栏模型需要一个支援 ICellCheckBox 接口的单元格。
每一个这些类别都包含一个或多个方便的只读实例的静态的特性
- SourceGrid2.VisualModels.Common.Default
- SourceGrid2.VisualModels.Common.LinkStyle
- SourceGrid2.VisualModels.CheckBox.Default
- SourceGrid2.VisualModels.CheckBox.MiddleLeftAlign
- SourceGrid2.VisualModels.Header.Default
- SourceGrid2.VisualModels.Header.ColumnHeader
- SourceGrid2.VisualModels.Header.RowHeader
这一个码表示该如何分配相同的 VisualModel 到较多的先前创建的单元格然后改变一些特性:
SourceGrid2.VisualModels.Common l_SharedVisualModel = new SourceGrid2.VisualModels.Common();
grid1[0,0].VisualModel = l_SharedVisualModel;
grid1[1,0].VisualModel = l_SharedVisualModel;
grid1[2,0].VisualModel = l_SharedVisualModel;
l_SharedVisualModel.BackColor = Color.LightGray;
也考虑当你写Cell.BackColor
特性自动地调用 VisualModel 的 BackColor 特性。
为了更便利的使用通常的一些属性,当你写诸这样的代码时:Cell.BackColor = Color.Black;
单元格自动地再一次到复制目前的 VisualModel, 将 backcolor 换成复制的实例而且分配复制的实例。
DataModel
Namespace: SourceGrid2.DataModels
用格式化的字符串来表示一个单元格的值时,通常是必须组装单元格DataModel
的属性
如果属性为空,是不能改变单元格的值
通常 DataModel 使用被请求的类型的 TypeConverter 处理必需的变换, 特别地字串变换.(过去一直表现单元格数值)
以下是名称空间SourceGrid2.DataModels:
的默认的DataModel类:
DataModelBase
–提供转换的方法,仅允许通过代码修改单元格的值;它不供应绘画接口。
EditorControlBase
:抽象类,帮助使用类似于单元格的编辑控件
EditorTextBox
-一个本文框编者。
EditorComboBox
EditorDateTime
EditorNumericUpDown
EditorTextBoxButton
:
有一个按钮的一个本文框编者开启一种明细窗体
EditorUITypeEditor
:
提供有 UITypeEditor 的所有类型的单元格编辑。许多类型支援这一个类别: DateTime ,Font,enum,.。。
一种DataModel
可以被许多单元格共享,就像为单元格的每一列使用相同的DataModel
产生一个可编辑的单元格有3种方法:
· 1.grid1[0,0] = new SourceGrid2.Cells.Real.Cell("Hello", typeof(string));
· 2。 SourceGrid2.DataModels.IDataModel l_SharedDataModel =
SourceGrid2.Utility.CreateDataModel(typeof(string));
grid1[0,0].DataModel = l_SharedDataModel;
grid1[1,0].DataModel = l_SharedDataModel;
· 3。SourceGrid2.DataModels.EditorTextBox l_TextBox =
new SourceGrid2.DataModels.EditorTextBox(typeof(string));
grid1[2,0].DataModel = l_TextBox;
这一个方法是可能共享在许多单元格之间的相同编辑器。
……(省略一段)
当然用订制的控件或特别的行为产生一个订制的 DataModel 编辑器是可能的。
下列的图片表示可得的大部份的编辑器和像图像特性一样的一些选择项:
BehaviorModel
Namespace: SourceGrid2.BehaviorModels
每个单元格都有一个BehaviorModel
的集合,你可以使用Behaviors
属性进行读取操作
BehaviorModel 是一个表示单元格的行为特色的类。 一个模型能在许多单元格之间被共享并且对任何新的功能的加入提供很好的弹性和简单性;
这些是类型 BehaviorModel 的默认类别:
SourceGrid2.BehaviorModels.Common
通常行为。
SourceGrid2.BehaviorModels.Header
表头的行为。
SourceGrid2.BehaviorModels.RowHeader
一个行表头的行为, 由于调整~大小功能。
SourceGrid2.BehaviorModels.ColumnHeader
- 一个栏表头的行为, 藉由分类而且调整~大小功能。 (需要 ICellSortableHeader接口)
SourceGrid2.BehaviorModels.CheckBox
* - 一个勾选栏的行为。 (需要 ICellCheckBox)
SourceGrid2.BehaviorModels.Cursor
*- 允许对一个特定的单元格一个光标的关联。 (需要 ICellCursor)
SourceGrid2.BehaviorModels.Button
-一个按钮的行为。
SourceGrid2.BehaviorModels.Resize
- 允许一个单元格与鼠标一起调整~大小.( 这一个模型自动地被表头模型用)
SourceGrid2.BehaviorModels.ToolTipText
* 把 ToolTipText 和一个单元格相连。 (需要 ICellToolTipText)
SourceGrid2.BehaviorModels.Unselectable
区块从收到焦点的一个单元格。
SourceGrid2.BehaviorModels.ContextMenu
*- 把 contextmenu 的成绩和一个单元格相连。 (需要 ICellContextMenu)
SourceGrid2.BehaviorModels.CustomEvents
SourceGrid2.BehaviorModels.BindProperty
SourceGrid2.BehaviorModels.BehaviorModelGroup
*与一个星号一起作记号的 BehaviorModel 需要特别的接口完成他们的任务,
举例来说类别勾选栏需要单元格支持接口 ICellCheckBox 。
每个类别有一些静态的特性返回类别的一个默认实例:
- SourceGrid2.BehaviorModels.Common.Default
- SourceGrid2.BehaviorModels.Button.Default
- SourceGrid2.BehaviorModels.CheckBox.Default
- SourceGrid2.BehaviorModels.ColumnHeader.SortHeader
- SourceGrid2.BehaviorModels.ColumnHeader.ResizeHeader
- SourceGrid2.BehaviorModels.ColumnHeader.SortResizeHeader
- SourceGrid2.BehaviorModels.ColumnHeader.NoSortNoResizeHeader
- SourceGrid2.BehaviorModels.ColumnHeader.Default
- SourceGrid2.BehaviorModels.Cursor.Default
- SourceGrid2.BehaviorModels.Header.Default
- SourceGrid2.BehaviorModels.Resize.ResizeHeight
- SourceGrid2.BehaviorModels.Resize.ResizeWidth
- SourceGrid2.BehaviorModels.Resize.ResizeBoth
- SourceGrid2.BehaviorModels.RowHeader.Default
- SourceGrid2.BehaviorModels.ToolTipText.Default
- SourceGrid2.BehaviorModels.Unselectable
在下列的码中当使用者在单元格之上移动鼠标的时候,我产生改变单元格的 backcolor 的 BehaviorModel 的例子
public class CustomBehavior : SourceGrid2.BehaviorModels.BehaviorModelGroup
{
public override void OnMouseEnter(SourceGrid2.PositionEventArgs e)
{
base.OnMouseEnter (e);
((SourceGrid2.Cells.Real.Cell)e.Cell).BackColor = Color.LightGreen;
}
public override void OnMouseLeave(SourceGrid2.PositionEventArgs e)
{
base.OnMouseLeave (e);
((SourceGrid2.Cells.Real.Cell)e.Cell).BackColor = Color.White;
}
}
//在窗体的加载事件中插入代码
grid1.Redim(2,2);
CustomBehavior l_Behavior = new CustomBehavior();
for (int r = 0; r < grid1.RowsCount; r++)
for (int c = 0; c < grid1.ColumnsCount; c++)
{
grid1[r,c] = new SourceGrid2.Cells.Real.Cell("Hello");
grid1[r,c].Behaviors.Add(l_Behavior);
}