介绍
表格控件是应用程序中使用频率最高的控件了,框架中对表格控件进行了一定的封装,使用起来更方便。框架中应该使用扩展控件XCI.Windows.Controls.GridControlx,将表格的配置保存在外部配置文件中,修改和调整参数不用重新编译,同时配和泛型数据操作类XCI.Windows.Helper.GridHelper<T>,一起完成数据操作。
使用
拖拽控件GridControlx到界面中,在.Designer.cs文件中会自动为表格控件生成Id属性,作用是标识表格,每个表格的Id属性都是唯一的,当保存表格的配置信息时,将以表格的Id值作为文件夹保存。
初始化
表格控件的操作需要借助GridHelper类来一起完成,在界面打开时需要先初始化GridHelper类。
//定义泛型类GridHelper为Form或者UserControl的成员变量private GridHelper<BasicCustomer> helper;//Load中初始化GridHelper实例变量的值,参数为表格视图变量private void Form2_Load(object sender, EventArgs e){helper = new GridHelper<BasicCustomer>(gridViewx1);}
表格配置在软件启动后,通过右键表格列菜单,进入配置页面,配置完成后点保存,保存到本地和服务器。如果要对配置表格按钮进行权限通知,需要给用户分配编码为sys.allowGridSetting的权限项即可。
实体数据
通过在实体类中添加属性,标注实体元数据。
/// <summary>/// 客户档案/// </summary>[Table("客户档案")]public class BasicCustomer{/// <summary>/// 客户主键/// </summary>[Primary][Column("客户主键", false)]public string Id { get; set; }/// <summary>/// 客户名称/// </summary>[Column("客户名称")][Required(ErrorMessage = "请输入客户名称")][StringLength(200, ErrorMessage = "客户名称不能超过200个字符")]public string Name { get; set; }/// <summary>/// 客户简称/// </summary>[Column("客户简称")][Required(ErrorMessage = "请输入客户简称")][StringLength(200, ErrorMessage = "客户简称不能超过200个字符")]public string ShortName { get; set; }}
ColumnAttribute
namespace XCI.Data.Entity{/// <summary>/// 列字段/// </summary>[AttributeUsage(AttributeTargets.Property)]public class ColumnAttribute : Attribute{/// <summary>/// 列字段/// </summary>public ColumnAttribute(){}/// <summary>/// 列字段/// </summary>/// <param name="caption">描述</param>public ColumnAttribute(string caption){Caption = caption;}/// <summary>/// 列字段/// </summary>/// <param name="caption">描述</param>/// <param name="visable">是否可见</param>public ColumnAttribute(string caption,bool visable){Caption = caption;Visable = visable;}/// <summary>/// 属性名称/// </summary>public string Name { get; internal set; }/// <summary>/// 列名/// </summary>public string DbName { get; set; }/// <summary>/// 描述/// </summary>public string Caption { get; set; }/// <summary>/// 导出/// </summary>public bool Export { get; set; } = true;/// <summary>/// 是否可见/// </summary>public bool Visable { get; set; } = true;}}
数据加载
通过调用相关服务,将数据读取之后,需要把数据渲染到界面。可以使用同步方法,也可以采用异步方法,推荐使用异步方法。
同步方法:这是默认值,同步方法的好处是代码按线性顺序执行,逻辑清晰简单。缺点是如果数据加载缓慢,主线程会卡死,界面将短时间内失去响应。
异步方法:异步方法的好处是数据读取将在新的线程中进行,不会阻塞主线程,界面不会卡顿。缺点是代码并行执行,写法相对繁琐。
同步
var list = BasicCustomerService.Instance.SelectList();helper.SetDataSource(list);
异步
helper.RunCallback(e => //定义获取数据回调函数{e.Result = BasicCustomerService.Instance.SelectList();}).CompletCallback(e => //定义数据绑定完成后回调函数{}).RunAsync(); //开始执行异步加载数据
分页
传统式
通过手动选择页数来确定加载哪一页的数据,数据显示的最大值是PageSize。优点是每次只显示某一页的数据,没有性能问题。

/// <summary>/// 数据加载/// </summary>/// <param name="pageIndex">页码</param>private void LoadData(int? pageIndex = null){helper.SetPageIndex(pageIndex);//设置页码参数,如果pageIndex为空,则不设置var paged = helper.Paged; //获取分页参数,包括页码、每页大小、排序列、排序方式//异步加载分页数据helper.RunCallback(e =>{e.Result = BasicCustomerService.Instance.SelectPageList(paged);}).CompletCallback(e =>{}).RunAsync();}
瀑布式
当滚动条滑动到每页最大值时,将自动加载下一页数据,数据显示会越来越多,直到所有数据全部加载完成。优点是当批量操作时可以同时操作大量的数据,缺点是当加载的数据越来越多时,内存占用过多,性能会下降。
//定义瀑布分页类成员变量private InfinitePage<BasicCustomer> infinitePage;//页码加载时,初始化瀑布分页类infinitePage = new InfinitePage<BasicCustomer>(gridCustomer, 200);infinitePage.LoadDataSource += (s, args) => //数据加载事件{args.PageList = BasicCustomerService.Instance.SelectPageList(args.PageParam);};infinitePage.ShowPageInfo += (s, args) => //显示分页信息事件{ControlInvoke(labPageInfoCustomer, () =>{labPageInfoCustomer.Text = infinitePage.FormatPageInfo(args.PageInfo);//格式化分页信息});};//开始加载分页信息gridCustomer.RefreshDataSource();
图片列
表格要显示图片,必须要添加一个图片列编辑控件,具体操作:Run Designer→In-place Editor Repository→添加PictureEdit。添加完成后在Columns标签页中找到图片列,设置列属性ColumnEdit,选择刚才添加的图片编辑控件。
如果数据直接就是存的图片二进制,直接把二进制列绑定到上面的图片列即可。
如果数据库存的是图片路径:
- 在实体中添加图片列:
public Image OriginImage { get; set; }
- 循环List,给图片字段赋值
foreach (var item in list.Rows){if (item.OriginImageUrl.IsNotEmpty() && File.Exists(item.OriginImageUrl)){item.OriginImage = ImageHelper.LoadImage(item.OriginImageUrl);}}
状态列
- 实体中添加状态列
/// <summary>/// 状态(0:作废;1:退回;2:申请:3:确认;)/// </summary>[Column("状态")]public int Status { get; set; }/// <summary>/// 状态(0:作废;1:退回;2:申请:3:确认;)/// </summary>[Column("状态文本")]public string StatusText{get{if (Status == 0){return "作废";}else if (Status == 1){return "退回";}else if (Status == 2){return "申请";}else if (Status == 3){return "确认";}return "未知";}}
- 界面中绑定新加的状态列 StatusText
排序
gridView.StartSorting += (o, e) => { helper.OnServerStartSorting(); };gridView.ColumnSortInfoChanged += (o, e) => { LoadData(); };
右键菜单
默认情况下,GridHelper会根据表格MenuManager属性中的按钮,自动生成右键菜单,也可以自己创建一个右键菜单对象,通过GridHelper构造函数传递进去。
GridHelper
属性
| Id | 表格标识 |
|---|---|
| IsReserveStatus | 保留状态 |
| DrawEmptyMessage | 数据为空时是否绘制空数据提示消息 |
| EmptyDataMessage | 数据为空时的空消息 |
| AutoPopupMenu | 自动生成右键菜单 |
| ElapsedTimeItem | 执行耗时显示控件 |
| IsFirstFocus | 当前焦点是否是第一行 |
| IsLastFocus | 当前焦点是否是最后一行 |
| HasMultiSelected | 当前是否选中多条 |
| HasData | 是否包含数据 |
| HasSingleSelected | 是否单选数据 |
| HasSelected | 是否选中数据(单选或者多选) |
| HasMultiChecked | 是否勾选数据(只针对多选) |
| SelectedId | 选中的主键 |
| Selected | 选中的对象 |
| SelectedIndex | 选中行索引(从0开始) |
| SelectedIndexs | 选中行索引数组 |
| SelectedList | 获取选中的对象列表 |
| SelectedIdList | 获取勾选的主键数组 |
| SelectedIds | 获取勾选的主键字符串,用逗号分开 |
| WorkElapsedTime | 数据加载耗时 |
方法
| AutoBuildColumn | 自动生成列 |
|---|---|
| CancelAsync | 请求取消的挂起的异步操作 |
| ClearSelectRow | 清除选中的行 |
| DblClickRow | 双击表格行 |
| Delete | 删除选中的数据 |
| Get | 获取指定行的对象 |
| GetRecordId | 获取主键值 |
| GetRowIndexByColumn | 根据列信息获取行索引 |
| GetRowIndexById | 根据主键获取行索引 |
| GetSetting | 获取表格配置 |
| SetSetting | 应用表格配置 |
| GotoPage | 转到指定页 |
| ShowSettingForm | 显示表格配置窗口 |
| OnUpDownMoveFocusRow | 当键盘按上下方向键时移动焦点行 |
| RunAsync | 开始执行异步操作 |
| RunCallback | 设置异步执行回调函数 |
| SelectRowById | 选中行使用主键 |
| SelectRowByIndex | 选中行使用序号 |
| SelectSingleRow | 选中单行使用序号 |
| SetDataSource | 设置数据源 |
| SetPageIndex | 设置页码 |
| SetPageSize | 设置分页大小 |
重要的事件
//行删除前触发private void GridViewx1_RowDeleting(object sender, DevExpress.Data.RowDeletingEventArgs e){}//行删除后触发private void GridViewx1_RowDeleted(object sender, DevExpress.Data.RowDeletedEventArgs e){}//行更新后触发private void GridViewx1_RowUpdated(object sender, DevExpress.XtraGrid.Views.Base.RowObjectEventArgs e){}//验证行事件private void GridViewx1_ValidateRow(object sender, DevExpress.XtraGrid.Views.Base.ValidateRowEventArgs e){}//列值发生变化前触发private void GridViewx1_CellValueChanging(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e){}//列值发生变化后触发private void GridViewx1_CellValueChanged(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e){}//焦点行索引变化时触发private void GridViewx1_FocusedRowChanged(object sender, DevExpress.XtraGrid.Views.Base.FocusedRowChangedEventArgs e){}//焦点行对象变化时触发private void GridViewx1_FocusedRowObjectChanged(object sender, DevExpress.XtraGrid.Views.Base.FocusedRowObjectChangedEventArgs e){}//选择行发生变化时触发(只有多选时才触发)private void GridViewx1_SelectionChanged(object sender, DevExpress.Data.SelectionChangedEventArgs e){}
