SourceGrid zt
SourceGrid介绍和使用及实例举例
先上图,来一个简单演示:

SourceGrid就是一个用于数据显示的表格控件,这个控件比c#自带的
DataGridView要强大很多,先不说他的原理,只说他的功能,可以实现各种自定义样式、嵌入各种控件,如checkbox、Combobox、
Button、超级链接、其他自定义控件等等,另外他不依赖于数据源显示,可以随意控制其显示的单元格;
一,使用方法:
1.1 首先去下载一个SourceGrid控件库,这个是开源控件,下载好后整理一套动态库,放入你的项目里,主要有以下几个:
DevAge.Core.dll //辅助核心
DevAge.Windows.Forms.dll //包装了用于winform里的某些控件的定义
log4net.dll //日志库
SourceGrid.dll //核心库
SourceGrid.Extensions.dll //扩展库
1.2 新建一个winform工程,将这些类库放入debug目录下,然后在工具箱点右键,选择项,点浏览,选择SourceGrid.dll,加入到工具箱;
然后像使用其他控件一样,拖到窗体上;

二,代码的编写;
SourceGrid一般都是以纯代码实现;
2.1首先我们建一个用于数据显示的对象:
public class Student
{
public string Name { get; set; }
public string Gender { get; set; }
public DateTime Birth { get; set; }
public int Fee { get; set; }
}
2.2 增加数据:
定义私有的实例变量:
private List<Student> students = null;
在窗体构造函数里初始化此变量:
students = new List<Student>()
{
new Student(){ Name="张三",Gender="1",Birth=DateTime.Parse("1989-1-1"),Fee = 2500},
new Student(){ Name="李四",Gender="0",Birth=DateTime.Parse("1989-12-10"),Fee = 2200},
new Student(){ Name="王五",Gender="0",Birth=DateTime.Parse("1989-4-4"),Fee = 2800}
};
2.3 在SourceGrid里显示,并统计所收学费总和;
2.3.1 定义方法GetData()
首先初始化列:
SourceGrid.Grid grid = grid1;
grid.BorderStyle = BorderStyle.FixedSingle;
grid.FixedRows = 1;
grid.FixedColumns = 1;
//初始化列
int gridColumnsCount = 5;//设定列数
int gridRowsCount = students.Count+2;//设定行数
int gridWith = this.Width - 20;//设定宽度为当前窗体宽度
int[] colsWidth = { 20, 160, 160, 100, 100 };//每列的宽度
string[] colsText = { "", "姓名", "性别", "生日", "已收学费" };//每列的标题
grid.Rows.Insert(0);
grid.ColumnsCount = gridColumnsCount;
grid.Width = gridWith;
int otherColsWidth = 0;
for (int i = 0; i < 5; i++)
{
SourceGrid.Cells.ColumnHeader head = new SourceGrid.Cells.ColumnHeader(colsText);
head.AutomaticSortEnabled = false;//禁止排序
if (i != grid.ColumnsCount - 1)
{
grid.Columns.Width = colsWidth;
otherColsWidth += colsWidth;
}
else
grid.Columns.Width = grid1.Width - otherColsWidth - 2 * i;//让最后一列铺满整个Grid
grid[0, i] = head;
}
其次,初始化行:
//初始化所有单元格
int rowsReadOnly = gridColumnsCount - 2;//设置某行为只读
for (int i = 0; i <gridRowsCount; i++)
{
int r = grid.RowsCount;
grid.Rows.Insert(r);
for (int j = 1; j < gridColumnsCount;j++ )
{
grid[r, j] = new SourceGrid.Cells.Cell("", typeof(string));
if (i == rowsReadOnly)
{
grid[r, j].Editor = null;
}
}
}
填充数据:
//赋值
int sum = 0;
for (int i = 0; i < students.Count; i++)
{
int r = i + 1;
grid[r, 1] .Value=students.Name;
grid[r, 2] .Value= students.Gender;
grid[r, 3] =new SourceGrid.Cells.Cell(students.Birth, typeof(DateTime));
grid[r, 4] =new SourceGrid.Cells.Cell(students.Fee, typeof(int));
sum += students.Fee;
}
//设置倒数第二行的高度,直接将最后一行挤到最底部;
grid.Rows[grid1.Rows.Count - 2].Height = grid1.Height - grid1.Rows[0].Height * (grid1.RowsCount) + 10;
//设置倒数第一行的内容
grid[grid.Rows.Count - 1, 1] = new SourceGrid.Cells.Cell("总计:", typeof(string));
grid[grid.Rows.Count - 1, 4] = new SourceGrid.Cells.Cell(sum.ToString() + "圆整", typeof(string));
摘录一段网上的描述:
每个单元格由 4 个基本部分组成, 它们基于改进的“模式-外观-控制器(Model-View-Controller)”模型
模式(Model): 模式是管理单元格取值的类, 它包含相关的取值或属性, 并且与其他组件相联系.
外观(View) : 外观是绘制单元格, 并包含可视属性的类.
控制器(Controller) : 控制器是提供单元格行为的类. 编辑器(Editor) :
编辑器是定制单元格的编辑器的类. 这种划分为代码提供了很大的弹性和可重用性, 可节约时间, 为每种定制类型提供可靠的基础。
为了较通用的要求一些类已经被准备和配置, 但是, 可能会需要以某些代码行建立个性化单元格。
简单的理解:
因此,如果想改变外观,就选择或者自定义VIEW,如果想要增加事件、行为,则要选择或者自定义控制器,如果想进去用合适的控件编辑,则要选择或自定义编辑器;
而单元格里面放的是个对象,这个对象可以是普通的单元格、也可以是按钮、也可以是其他类型,等等;
具体的描述性文档可以参照网上的详细介绍:
http://wenku.baidu.com/view/9bde88eb0975f46527d3e156.html
下面给大家列举一个实用的例子
先上图:

实现的功能:
1,自定义列,最后一列铺满整个grid;
2,第0列放一个按钮,单击此按钮可以弹出窗口,选择新窗口的某条记录,记录的结果显示在此行相应的单元格里;
3,性别的选择为下拉列表,且只能是枚举里的值;
4,生日的选择只能为日期,可以弹出日期选择框选择;
5,当前的行用满了,则可以右键增加一行;
6,可以删除选择的行;
相应的代码:
定义几个实例变量:
private int gridRowsCount = 10;//设定行数
private int gridColumnsCount = 5;//设定列数
private int[] colsWidth = { 20, 160, 160, 100, 100 };//每列的宽度
private string[] colsText = { "", "姓名", "性别", "生日", "已收学费" };//每列的标题
定义一个初始化GRID方法,基本都有注解
private void GetGrid()
{
SourceGrid.Grid grid = grid1;
#region 初始化grid
grid.Redim(gridRowsCount, gridColumnsCount);
//选择模式为行
grid.SelectionMode = SourceGrid.GridSelectionMode.Row;
//设置固定列和固定行
grid.FixedColumns = 1;
grid.FixedRows = 1;
//初始化列,最后一列铺满整个grid
for (int i = 0,otherColsWidth = 0; i < gridColumnsCount; i++)
{
SourceGrid.Cells.ColumnHeader head = new SourceGrid.Cells.ColumnHeader(colsText[i]);
head.AutomaticSortEnabled = false;//取消自动排序
if (i != grid.ColumnsCount - 1)//不是最后一列
{
grid.Columns[i].Width = colsWidth[i];
otherColsWidth += colsWidth[i];
}
else //设置最后一列铺满整个grid
grid.Columns[i].Width = grid1.Width - otherColsWidth - 2 * i;
grid[0, i] = head;
}
//初始化行
for (int i = 1; i < gridRowsCount; i++)
{
IniOneRow(i);
}
#endregion
}
其中有个初始化某行,代码见下:
/// <summary>
/// 初始化一行
/// </summary>
/// <param name="rowIndex"></param>
private void IniOneRow(int rowIndex)
{
SourceGrid.Grid grid = grid1;
//单击控制器
SourceGrid.Cells.Controllers.Button buttonClickEvent = new SourceGrid.Cells.Controllers.Button();
buttonClickEvent.Executed += new EventHandler(CellButton_Click);
//下拉框 暂时没用到
//SourceGrid.Cells.Editors.ComboBox cbEditor = new SourceGrid.Cells.Editors.ComboBox(typeof(EnumGender));
//cbEditor.StandardValues = new EnumGender[] { EnumGender.男, EnumGender.女 };
//cbEditor.EditableMode = SourceGrid.EditableMode.Focus |
SourceGrid.EditableMode.SingleClick | SourceGrid.EditableMode.AnyKey;
//日期编辑器
SourceGrid.Cells.Editors.TextBoxUITypeEditor editorDateTime =
new SourceGrid.Cells.Editors.TextBoxUITypeEditor(typeof(DateTime));
PopupMenu menuController = new PopupMenu(this);
for (int j = 0; j < gridColumnsCount; j++)
{
if (j == 0)
{
//单元格设置为按钮
grid[rowIndex, j] = new SourceGrid.Cells.Button("…");
//存放某些必须的信息,如关键字
grid[rowIndex, j].Tag = rowIndex;
//为按钮增加事件
grid[rowIndex, j].AddController(buttonClickEvent);
}
else if (j == 2)
{
//设置为枚举类型,激活之后将会显示为下拉框
grid[rowIndex, j] = new SourceGrid.Cells.Cell(null, typeof(EnumGender));
//grid[i, j].Editor = cbEditor;
//grid[i, j].View = SourceGrid.Cells.Views.ComboBox.Default;
}
else if (j == 3)//日期格式,控制其 显示和输入
{
grid[rowIndex, j] = new SourceGrid.Cells.Cell("", typeof(DateTime));
grid1[rowIndex, j].Editor = editorDateTime;
}
else
grid[rowIndex, j] = new SourceGrid.Cells.Cell("", typeof(string));
//设置每行的激活编辑方式
if (grid[rowIndex, j].Editor!=null)
grid[rowIndex, j].Editor.EditableMode = SourceGrid.EditableMode.Focus | SourceGrid.EditableMode.SingleClick;
//grid[rowIndex, j].Editor.EditableMode =
SourceGrid.EditableMode.Focus | SourceGrid.EditableMode.SingleClick |
SourceGrid.EditableMode.AnyKey;
//为每个行增加右键菜单
grid[rowIndex, j].AddController(menuController);
}
}
这里稍微有点复杂:
1,了解按钮控件如何放单元格里;
2,按钮的事件如何关联
2,了解枚举类型如何处理;
3,如何增加菜单。对于菜单部分,还有部分代码如下:
本帖最后由 繁华都市 于 2013-1-11 10:57 编辑
/// <summary>
/// 按钮单击事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CellButton_Click(object sender, EventArgs e)
{
SourceGrid.CellContext context = (SourceGrid.CellContext)sender;
SourceGrid.Cells.Button btnCell = (SourceGrid.Cells.Button)context.Cell;
string id = btnCell.Tag.ToString();
MessageBox.Show(id);
Student stu = new Student() { Name = "张三", Gender = "1", Birth = DateTime.Parse("1991-1-1"), Fee = 2500 };
EnumGender sGender = stu.Gender == "1" ? EnumGender.男 : EnumGender.女;
int currenRow = btnCell.Row.Index;
grid1[currenRow, 1].Value = stu.Name;
grid1[currenRow, 2].Value = sGender;
grid1[currenRow, 3].Value = stu.Birth;
grid1[currenRow, 4].Value = stu.Fee;
}
下面是菜单的两个操作定义:
/// <summary>
/// 新增一行
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void Menu1_Click(object sender, EventArgs e)
{
int i = grid1.RowsCount;
grid1.Rows.Insert(i);
IniOneRow(i);
}
/// <summary>
/// 删除一行
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void Menu2_Click(object sender, EventArgs e)
{
//TODO Your code here
int[] rowsIndex = grid1.Selection.GetSelectionRegion().GetRowsIndex();
SourceGrid.RowInfo[] rows = new SourceGrid.RowInfo[rowsIndex.Length];
for (int i = 0; i < rows.Length; i++)
rows = grid1.Rows[rowsIndex【i】];
foreach (SourceGrid.RowInfo r in rows)
grid1.Rows.Remove(r.Index);
if (grid1.RowsCount > 1)
grid1.Selection.FocusRow(1);
}
菜单控制器的定义如下:
public class PopupMenu : SourceGrid.Cells.Controllers.ControllerBase
{
ContextMenu menu = new ContextMenu();
private FormGridEdit mFrm;
public PopupMenu(FormGridEdit frm)
{
mFrm = frm;
menu.MenuItems.Add("新增一行", new EventHandler(mFrm.Menu1_Click));
menu.MenuItems.Add("删除选中的行", new EventHandler(mFrm.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));
}
}
性别的枚举:
/// <summary>
/// 枚举,为下拉框准备
/// </summary>
public enum EnumGender
{
男,
女,
无
}
SourceGrid zt的更多相关文章
- http://kb.cnblogs.com/zt/ef/
http://kb.cnblogs.com/zt/ef/ http://blog.csdn.net/mackz/article/details/8605063 http://www.telerik.c ...
- 解决SourceGrid在某些系统上无法用鼠标滚轮滚动的问题
4.40版源码,找到SourceGrid/SourceGrid/Common/CustomScrollControl.cs 这个文件 定位 CustomScrollWheel() 方法,把if条件判断 ...
- [ZT] Vim快捷键分类
一. 移动: h,j,k,l: 左,下,上,右. w: 下一个词的词首. e:下一个词的词尾. b:上一个词的词首. <>: v 模式选中后进行缩进.二. 跳 ...
- 如何杀掉D状态的进程?[zt]【转】
转自:http://blog.csdn.net/chinalinuxzend/article/details/4288791 [-] 如何杀掉D状态的进程zt 相关博文 原贴:http://www ...
- 33条C#、.Net经典面试题目及答案[zt]
33条C#..Net经典面试题目及答案[zt] 本文集中了多条常见的C#..Net经典面试题目例如“.NET中类和结构的区别”.“ASP.NET页面之间传递值的几种方式?”,并简明扼要的给出了答案,希 ...
- Asp.NET MVC 技术参考:http://kb.cnblogs.com/zt/mvc/
Asp.NET MVC 技术参考:http://kb.cnblogs.com/zt/mvc/
- Entity Framework 技术参考:http://kb.cnblogs.com/zt/ef/
Entity Framework 技术参考:http://kb.cnblogs.com/zt/ef/
- rdlc部署zt
原文:rdlc部署zt 偶然间遇到“ 未能加载文件或程序集microsoft.reportviewer.winforms ……”的一个错误,以前web是遇到过,没想到winform部署也会遇到.找了半 ...
- javamail接收邮件(zt)
zt from:http://xiangzhengyan.iteye.com/blog/85961 import <a href="http://lib.csdn.net/base/j ...
随机推荐
- vim中编写python代码使用python-mode和syntastic插件时警告(Warning)的消除
问题: 在Vim使用了syntastic后,编写代码时,可以对代码错误和警告进行相对实时的了解,对编写代码有很大的帮助.同时这个插件和python-mode一起工作时,可以对python代码的编写提供 ...
- java对象数组
问题描述: java 对象数组的使用 问题解决: 数组元素可以是任何类型(只要所有元素具有相同的类型) 数组元素可以是基本数据类型 数组元素也可以是类对象,称这样的数组为对象数组.在这种情况下 ...
- Emoji表情符号兼容方案(适用ios,android,wp等平台)
http://blog.csdn.net/qdkfriend/article/details/7576524 Emoji表情符号兼容方案 一 什么是Emoji emoji就是表情符号:词义来自日语(え ...
- hdu 1525 Euclid's Game 博弈论
思路:两个数a和b,总会出现的一个局面是b,a%b,这是必然的,如果a>=b&&a<2*b,那么只有一种情况,直接到b,a%b.否则有多种情况. 对于a/b==1这种局面, ...
- win8.1下使用vmware workstation 来编译ffmpeg
先吐槽下,T440预装的win8.1 采用 UEFI+GPT分区导致 无法使用传统的EasyBCD来达到win+ubuntu双系统效果, 尝试了2天全部失败,等以后有时间了 买块U盘再干掉win8 现 ...
- jmeter summariser(命令行执行时的输出) 、查看结果树等结果中文乱码
在使用jmeter测试时,如果你的sampler名字为中文.或者输出的结果信息有中文,你会发现它们都是乱码,非常蛋碎!原因是: jmeter的默认编码为:ISO-8859-1, 解决方案就是要修改它 ...
- iOS开发的小技巧(断点打印)
iOS开发中我们会碰到这样的需求:打印沙盒目录,打印对象信息,对象信息可以通过断点查看,有时候对象属性繁多时看起来又比较麻烦. 今天学到一个比较实用的方法: 在运行时打一个断点,当程序停在这个断点后, ...
- Android:实现退出确认对话框
在Android平台上捕获Back键的事件,super.onBackPressed()是执行系统的默认动作,就是退出当前activity,我们要做的就是重写onBackPressed()函数, pub ...
- 精选7款绚丽的HTML5和jQuery图片动画特效
在HTML5出现后,图片就变得更加富有动感了,各种图片动画特效也层出不穷,例如图片播放器.图片导航.3D图片动画等等.本文将精选几款具有代表性的HTML5和jQuery图片动画特效,绚丽的画面.实用的 ...
- uva 11292 Dragon of Loowater (勇者斗恶龙)
Problem C: The Dragon of Loowater Once upon a time, in the Kingdom of Loowater, a minor nuisance tur ...