介绍

表格控件是应用程序中使用频率最高的控件了,框架中对表格控件进行了一定的封装,使用起来更方便。框架中应该使用扩展控件XCI.Windows.Controls.GridControlx,将表格的配置保存在外部配置文件中,修改和调整参数不用重新编译,同时配和泛型数据操作类XCI.Windows.Helper.GridHelper<T>,一起完成数据操作。

使用

拖拽控件GridControlx到界面中,在.Designer.cs文件中会自动为表格控件生成Id属性,作用是标识表格,每个表格的Id属性都是唯一的,当保存表格的配置信息时,将以表格的Id值作为文件夹保存。

初始化

表格控件的操作需要借助GridHelper类来一起完成,在界面打开时需要先初始化GridHelper类。

  1. //定义泛型类GridHelper为Form或者UserControl的成员变量
  2. private GridHelper<BasicCustomer> helper;
  3. //Load中初始化GridHelper实例变量的值,参数为表格视图变量
  4. private void Form2_Load(object sender, EventArgs e)
  5. {
  6. helper = new GridHelper<BasicCustomer>(gridViewx1);
  7. }

表格配置在软件启动后,通过右键表格列菜单,进入配置页面,配置完成后点保存,保存到本地和服务器。如果要对配置表格按钮进行权限通知,需要给用户分配编码为sys.allowGridSetting的权限项即可。

实体数据

通过在实体类中添加属性,标注实体元数据。

  1. /// <summary>
  2. /// 客户档案
  3. /// </summary>
  4. [Table("客户档案")]
  5. public class BasicCustomer
  6. {
  7. /// <summary>
  8. /// 客户主键
  9. /// </summary>
  10. [Primary]
  11. [Column("客户主键", false)]
  12. public string Id { get; set; }
  13. /// <summary>
  14. /// 客户名称
  15. /// </summary>
  16. [Column("客户名称")]
  17. [Required(ErrorMessage = "请输入客户名称")]
  18. [StringLength(200, ErrorMessage = "客户名称不能超过200个字符")]
  19. public string Name { get; set; }
  20. /// <summary>
  21. /// 客户简称
  22. /// </summary>
  23. [Column("客户简称")]
  24. [Required(ErrorMessage = "请输入客户简称")]
  25. [StringLength(200, ErrorMessage = "客户简称不能超过200个字符")]
  26. public string ShortName { get; set; }
  27. }

ColumnAttribute

  1. namespace XCI.Data.Entity
  2. {
  3. /// <summary>
  4. /// 列字段
  5. /// </summary>
  6. [AttributeUsage(AttributeTargets.Property)]
  7. public class ColumnAttribute : Attribute
  8. {
  9. /// <summary>
  10. /// 列字段
  11. /// </summary>
  12. public ColumnAttribute()
  13. {
  14. }
  15. /// <summary>
  16. /// 列字段
  17. /// </summary>
  18. /// <param name="caption">描述</param>
  19. public ColumnAttribute(string caption)
  20. {
  21. Caption = caption;
  22. }
  23. /// <summary>
  24. /// 列字段
  25. /// </summary>
  26. /// <param name="caption">描述</param>
  27. /// <param name="visable">是否可见</param>
  28. public ColumnAttribute(string caption,bool visable)
  29. {
  30. Caption = caption;
  31. Visable = visable;
  32. }
  33. /// <summary>
  34. /// 属性名称
  35. /// </summary>
  36. public string Name { get; internal set; }
  37. /// <summary>
  38. /// 列名
  39. /// </summary>
  40. public string DbName { get; set; }
  41. /// <summary>
  42. /// 描述
  43. /// </summary>
  44. public string Caption { get; set; }
  45. /// <summary>
  46. /// 导出
  47. /// </summary>
  48. public bool Export { get; set; } = true;
  49. /// <summary>
  50. /// 是否可见
  51. /// </summary>
  52. public bool Visable { get; set; } = true;
  53. }
  54. }

数据加载

通过调用相关服务,将数据读取之后,需要把数据渲染到界面。可以使用同步方法,也可以采用异步方法,推荐使用异步方法。

同步方法:这是默认值,同步方法的好处是代码按线性顺序执行,逻辑清晰简单。缺点是如果数据加载缓慢,主线程会卡死,界面将短时间内失去响应。

异步方法:异步方法的好处是数据读取将在新的线程中进行,不会阻塞主线程,界面不会卡顿。缺点是代码并行执行,写法相对繁琐。

同步

  1. var list = BasicCustomerService.Instance.SelectList();
  2. helper.SetDataSource(list);

异步

  1. helper.RunCallback(e => //定义获取数据回调函数
  2. {
  3. e.Result = BasicCustomerService.Instance.SelectList();
  4. })
  5. .CompletCallback(e => //定义数据绑定完成后回调函数
  6. {
  7. })
  8. .RunAsync(); //开始执行异步加载数据

分页

传统式

通过手动选择页数来确定加载哪一页的数据,数据显示的最大值是PageSize。优点是每次只显示某一页的数据,没有性能问题。

image.png

  1. /// <summary>
  2. /// 数据加载
  3. /// </summary>
  4. /// <param name="pageIndex">页码</param>
  5. private void LoadData(int? pageIndex = null)
  6. {
  7. helper.SetPageIndex(pageIndex);//设置页码参数,如果pageIndex为空,则不设置
  8. var paged = helper.Paged; //获取分页参数,包括页码、每页大小、排序列、排序方式
  9. //异步加载分页数据
  10. helper.RunCallback(e =>
  11. {
  12. e.Result = BasicCustomerService.Instance.SelectPageList(paged);
  13. })
  14. .CompletCallback(e =>
  15. {
  16. })
  17. .RunAsync();
  18. }

瀑布式

当滚动条滑动到每页最大值时,将自动加载下一页数据,数据显示会越来越多,直到所有数据全部加载完成。优点是当批量操作时可以同时操作大量的数据,缺点是当加载的数据越来越多时,内存占用过多,性能会下降。
image.png

  1. //定义瀑布分页类成员变量
  2. private InfinitePage<BasicCustomer> infinitePage;
  3. //页码加载时,初始化瀑布分页类
  4. infinitePage = new InfinitePage<BasicCustomer>(gridCustomer, 200);
  5. infinitePage.LoadDataSource += (s, args) => //数据加载事件
  6. {
  7. args.PageList = BasicCustomerService.Instance.SelectPageList(args.PageParam);
  8. };
  9. infinitePage.ShowPageInfo += (s, args) => //显示分页信息事件
  10. {
  11. ControlInvoke(labPageInfoCustomer, () =>
  12. {
  13. labPageInfoCustomer.Text = infinitePage.FormatPageInfo(args.PageInfo);//格式化分页信息
  14. });
  15. };
  16. //开始加载分页信息
  17. gridCustomer.RefreshDataSource();

图片列

表格要显示图片,必须要添加一个图片列编辑控件,具体操作:Run Designer→In-place Editor Repository→添加PictureEdit。添加完成后在Columns标签页中找到图片列,设置列属性ColumnEdit,选择刚才添加的图片编辑控件。

如果数据直接就是存的图片二进制,直接把二进制列绑定到上面的图片列即可。

如果数据库存的是图片路径:

  1. 在实体中添加图片列:
  1. public Image OriginImage { get; set; }
  1. 循环List,给图片字段赋值
    1. foreach (var item in list.Rows)
    2. {
    3. if (item.OriginImageUrl.IsNotEmpty() && File.Exists(item.OriginImageUrl))
    4. {
    5. item.OriginImage = ImageHelper.LoadImage(item.OriginImageUrl);
    6. }
    7. }

状态列

  1. 实体中添加状态列
  1. /// <summary>
  2. /// 状态(0:作废;1:退回;2:申请:3:确认;)
  3. /// </summary>
  4. [Column("状态")]
  5. public int Status { get; set; }
  6. /// <summary>
  7. /// 状态(0:作废;1:退回;2:申请:3:确认;)
  8. /// </summary>
  9. [Column("状态文本")]
  10. public string StatusText
  11. {
  12. get
  13. {
  14. if (Status == 0)
  15. {
  16. return "作废";
  17. }
  18. else if (Status == 1)
  19. {
  20. return "退回";
  21. }
  22. else if (Status == 2)
  23. {
  24. return "申请";
  25. }
  26. else if (Status == 3)
  27. {
  28. return "确认";
  29. }
  30. return "未知";
  31. }
  32. }
  1. 界面中绑定新加的状态列 StatusText

排序

  1. gridView.StartSorting += (o, e) => { helper.OnServerStartSorting(); };
  2. 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 设置分页大小

重要的事件

  1. //行删除前触发
  2. private void GridViewx1_RowDeleting(object sender, DevExpress.Data.RowDeletingEventArgs e)
  3. {
  4. }
  5. //行删除后触发
  6. private void GridViewx1_RowDeleted(object sender, DevExpress.Data.RowDeletedEventArgs e)
  7. {
  8. }
  9. //行更新后触发
  10. private void GridViewx1_RowUpdated(object sender, DevExpress.XtraGrid.Views.Base.RowObjectEventArgs e)
  11. {
  12. }
  13. //验证行事件
  14. private void GridViewx1_ValidateRow(object sender, DevExpress.XtraGrid.Views.Base.ValidateRowEventArgs e)
  15. {
  16. }
  17. //列值发生变化前触发
  18. private void GridViewx1_CellValueChanging(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e)
  19. {
  20. }
  21. //列值发生变化后触发
  22. private void GridViewx1_CellValueChanged(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e)
  23. {
  24. }
  25. //焦点行索引变化时触发
  26. private void GridViewx1_FocusedRowChanged(object sender, DevExpress.XtraGrid.Views.Base.FocusedRowChangedEventArgs e)
  27. {
  28. }
  29. //焦点行对象变化时触发
  30. private void GridViewx1_FocusedRowObjectChanged(object sender, DevExpress.XtraGrid.Views.Base.FocusedRowObjectChangedEventArgs e)
  31. {
  32. }
  33. //选择行发生变化时触发(只有多选时才触发)
  34. private void GridViewx1_SelectionChanged(object sender, DevExpress.Data.SelectionChangedEventArgs e)
  35. {
  36. }