在Winform开发中,我们往往除了常规的单表信息录入外,有时候设计到多个主从表的数据显示、编辑等界面,单表的信息一般就是控件和对象实体一一对应,然后调用API保存即可,主从表就需要另外特殊处理,本随笔介绍如何快速实现主从表编辑界面的处理,结合GridControl控件的GridView控件对象,实现数据在列表中的实时编辑,非常方便。

1、主从表的界面设计及展示

主从表一般涉及两个以上的表,一个是主表,其他的是从表的,在实际情况下,一般包含两个表较多,我们这里以两个表的主从表关系进行分析处理。

例如我们建立两个报销申请单表关系如下所示。

对于报销的主从表信息,我们可以在列表中进行展示,如下界面所示,分为两部分:一部分是主表信息,一部分是从表信息,单击主表信息后,显示对应从表的列表信息。

那么我们新增一条主表记录的时候,那么可以弹出一个新的界面进行数据的维护处理,方便我们录入主从表的信息,界面如下所示。

上面界面包括了主表信息,以及从表的信息(在GridView中实时录入)两部分,这样填写后统一进行提交处理。

2、主从表编辑界面的处理

这里主要介绍一下主从表的编辑界面处理,也就是上面这个界面的实现处理。

其中初始化GridView的代码如下所示。

  1. /// <summary>
  2. /// 初始化明细表的GridView数据显示
  3. /// </summary>
  4. private void InitDetailGrid()
  5. {
  6. //初始清空列
  7. this.gridView1.Columns.Clear();
  8. //设置部分列隐藏
  9. this.gridView1.CreateColumn("ID", "编号").Visible = false;
  10. this.gridView1.CreateColumn("Header_ID", "主表编号").Visible = false;
  11. this.gridView1.CreateColumn("Apply_ID", "申请单编号").Visible = false;
  12. //添加下拉列表列,并绑定数据源
  13. this.gridView1.CreateColumn("FeeType", "费用类型", ).CreateComboBox().BindDictItems("费用类型");
  14. //创建日期列并指定格式
  15. var OccurTime = this.gridView1.CreateColumn("OccurTime", "发生时间", ).CreateDateEdit();
  16. OccurTime.EditMask = "yyyy-MM-dd HH:mm";
  17. OccurTime.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm";
  18. //创建数值列
  19. this.gridView1.CreateColumn("FeeAmount", "费用金额").CreateSpinEdit();
  20. //创建备注列
  21. this.gridView1.CreateColumn("FeeDescription", "费用说明", ).CreateMemoEdit();
  22.  
  23. //初始化GridView,可以新增列
  24. this.gridView1.InitGridView(GridType.NewItem, false, EditorShowMode.MouseDownFocused, "");
  25. //转义列内容显示
  26. this.gridView1.CustomColumnDisplayText += new CustomColumnDisplayTextEventHandler(gridView1_CustomColumnDisplayText);
  27. //处理单元格的样式
  28. this.gridView1.RowCellStyle += new RowCellStyleEventHandler(gridView1_RowCellStyle);
  29. //不允许头部排序
  30. this.gridView1.OptionsCustomization.AllowSort = false;
  31. //绘制序号
  32. this.gridView1.CustomDrawRowIndicator += (s, e) =>
  33. {
  34. if (e.Info.IsRowIndicator && e.RowHandle >= )
  35. {
  36. e.Info.DisplayText = (e.RowHandle + ).ToString();
  37. }
  38. };
  39.  
  40. //对输入单元格进行非空校验
  41. this.gridView1.ValidateRow += delegate(object sender, ValidateRowEventArgs e)
  42. {
  43. var result = gridControl1.ValidateRowNull(e, new string[]
  44. {
  45. "FeeType"
  46. });
  47. };
  48. //新增行的内容初始化
  49. this.gridView1.InitNewRow += (s, e) =>
  50. {
  51. gridView1.SetRowCellValue(e.RowHandle, "ID", Guid.NewGuid().ToString());
  52. gridView1.SetRowCellValue(e.RowHandle, "Header_ID", tempInfo.ID);
  53. gridView1.SetRowCellValue(e.RowHandle, "Apply_ID", tempInfo.Apply_ID);
  54. gridView1.SetRowCellValue(e.RowHandle, "OccurTime", DateTime.Now);
  55. };
  56. }
  57.  
  58. void gridView1_RowCellStyle(object sender, DevExpress.XtraGrid.Views.Grid.RowCellStyleEventArgs e)
  59. {
  60. GridView gridView = this.gridView1;
  61. if (e.Column.FieldName == "FeeAmount")
  62. {
  63. e.Appearance.BackColor = Color.Green;
  64. e.Appearance.BackColor2 = Color.LightCyan;
  65. }
  66. }
  67. void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e)
  68. {
  69. string columnName = e.Column.FieldName;
  70.  
  71. if (e.Column.ColumnType == typeof(DateTime))
  72. {
  73. if (e.Value != null)
  74. {
  75. if (e.Value == DBNull.Value || Convert.ToDateTime(e.Value) <= Convert.ToDateTime("1900-1-1"))
  76. {
  77. e.DisplayText = "";
  78. }
  79. else
  80. {
  81. e.DisplayText = Convert.ToDateTime(e.Value).ToString("yyyy-MM-dd HH:mm");//yyyy-MM-dd
  82. }
  83. }
  84. }
  85. }

上面代码都有详细的备注,主要就是我们根据数据库表的关系,创建对应显示的字段即可,其中有需要隐藏的那么就不要显示(方便获取对应的值)

  1. //设置部分列隐藏
  2. this.gridView1.CreateColumn("ID", "编号").Visible = false;
  3. this.gridView1.CreateColumn("Header_ID", "主表编号").Visible = false;
  4. this.gridView1.CreateColumn("Apply_ID", "申请单编号").Visible = false;

如果需要绑定下拉列表类似的字段,那么创建对应的数据类型,然后调用绑定函数绑定即可,如下面代码

  1. //添加下拉列表列,并绑定数据源
  2. this.gridView1.CreateColumn("FeeType", "费用类型", ).CreateComboBox().BindDictItems("费用类型");

如果是一些特殊的输入需要设置格式显示或者掩码,那么如下所示

  1. //创建日期列并指定格式
  2. var OccurTime = this.gridView1.CreateColumn("OccurTime", "发生时间", ).CreateDateEdit();
  3. OccurTime.EditMask = "yyyy-MM-dd HH:mm";
  4. OccurTime.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm";

另外有一个值得注意的就是我们新增一行从表记录的时候,需要记录一些主表的属性,这样的话,我们就是在行初始化的时候,赋值给从表的隐藏列即可。

  1. //新增行的内容初始化
  2. this.gridView1.InitNewRow += (s, e) =>
  3. {
  4. gridView1.SetRowCellValue(e.RowHandle, "ID", Guid.NewGuid().ToString());
  5. gridView1.SetRowCellValue(e.RowHandle, "Header_ID", tempInfo.ID);
  6. gridView1.SetRowCellValue(e.RowHandle, "Apply_ID", tempInfo.Apply_ID);
  7. gridView1.SetRowCellValue(e.RowHandle, "OccurTime", DateTime.Now);
  8. };

在界面中如果我们需要显示主表的信息,那么就根据条件获取对应的主表记录对象,然后显示给界面控件即可。

  1. /// <summary>
  2. /// 显示常规的对象内容
  3. /// </summary>
  4. /// <param name="info"></param>
  5. private void DisplayInfo(ReimbursementInfo info)
  6. {
  7. tempInfo = info;//重新给临时对象赋值,使之指向存在的记录对象
  8.  
  9. txtCategory.Text = info.Category;
  10. txtReason.Text = info.Reason;
  11. txtTotalAmount.Value = info.TotalAmount;
  12. txtNote.Text = info.Note;
  13. }

而保存的时候,我们把界面内容重新赋值给对应的主表对象。

  1. /// <summary>
  2. /// 编辑或者保存状态下取值函数
  3. /// </summary>
  4. /// <param name="info"></param>
  5. private void SetInfo(ReimbursementInfo info)
  6. {
  7. info.Category = txtCategory.Text;
  8. info.Reason = txtReason.Text;
  9. info.TotalAmount = txtTotalAmount.Value;
  10. info.Note = txtNote.Text;
  11.  
  12. info.ApplyDate = DateTime.Now;
  13. info.ApplyDept = base.LoginUserInfo.DeptId;
  14. info.CurrentLoginUserId = base.LoginUserInfo.ID;
  15. }

而我们需要获取GridView明细输入的时候,就通过一个函数遍历获取GridView的行记录,转换为相应的对象即可,如下所示。

  1. /// <summary>
  2. /// 获取明细列表
  3. /// </summary>
  4. /// <returns></returns>
  5. private List<ReimbursementDetailInfo> GetDetailList()
  6. {
  7. var list = new List<ReimbursementDetailInfo>();
  8. for (int i = ; i < this.gridView1.RowCount; i++)
  9. {
  10. var detailInfo = gridView1.GetRow(i) as ReimbursementDetailInfo;
  11. if (detailInfo != null)
  12. {
  13. list.Add(detailInfo);
  14. }
  15. }
  16. return list;
  17. }

这样处理完这些信息后,我们就可以在主表保存的时候,同时保存明细表信息即可。

  1. /// <summary>
  2. /// 新增状态下的数据保存
  3. /// </summary>
  4. /// <returns></returns>
  5. public override bool SaveAddNew()
  6. {
  7. ReimbursementInfo info = tempInfo;//必须使用存在的局部变量,因为部分信息可能被附件使用
  8. SetInfo(info);
  9. info.Creator = base.LoginUserInfo.ID;
  10. info.CreateTime = DateTime.Now;
  11.  
  12. try
  13. {
  14. #region 新增数据
  15.  
  16. bool succeed = BLLFactory<Reimbursement>.Instance.Insert(info);
  17. if (succeed)
  18. {
  19. //可添加其他关联操作
  20. var list = GetDetailList();
  21. foreach(var detailInfo in list)
  22. {
  23. BLLFactory<ReimbursementDetail>.Instance.InsertUpdate(detailInfo, detailInfo.ID);
  24. }
  25.  
  26. return true;
  27. }
  28. #endregion
  29. }
  30. catch (Exception ex)
  31. {
  32. LogTextHelper.Error(ex);
  33. MessageDxUtil.ShowError(ex.Message);
  34. }
  35. return false;
  36. }

其中代码

  1. BLLFactory<ReimbursementDetail>.Instance.InsertUpdate(detailInfo, detailInfo.ID);

可以对新增记录保存,也可以对存在的记录进行更新。

通过上面的介绍,我们可以看到不同的主从表其实逻辑还是很通用的,我们可以把它们的逻辑抽取出来,通过代码生成工具进行快速生成即可。

Winform界面中主从表编辑界面的快速处理的更多相关文章

  1. DataSnap ClientdataSet 三层中主从表的操作

    非原创  摘自:http://hi.baidu.com/yagzh2000/blog/item/fc69df2cb9845de78b139946.html三层中主从表的操作(删除.新增.修改)一定要在 ...

  2. QT向界面中嵌套新的界面

    简单说下 想要实现的内容 我们有一个主窗口mainwindow,需要向其中放入新的界面,你可以自己定义里面内容. 大致的效果图如下 实现起来就是利用QT的layout布局 使用水平布局QHboxlay ...

  3. 在Winform框架界面中改变并存储界面皮肤样式

    在本篇介绍的Winform界面样式改变及存储操作中,是指基于DevExpress进行界面样式的变化.一般情况下,默认我们会为客户提供多种DevExpress的界面皮肤以供个人喜好选择,默认DevExp ...

  4. 代码生成工具Database2Sharp中增加视图的代码生成以及主从表界面生成功能

    在代码生成工具的各种功能规划中,我们一向以客户的需求作为驱动,因此也会根据需要增加一些特殊的功能或者处理.在实际的开发中,虽然我们一般以具体的表进行具体业务开发,但是有些客户提出有时候视图开发也是很常 ...

  5. 在Vue前端界面中,几种数据表格的展示处理,以及表格编辑录入处理操作。

    在Vue前端项目中,我这里主要是基于Vue+Element的开发,大多数情况下,我们利用Element的表格组件就可以满足大多数情况的要求,本篇随笔针对表格的展示和编辑处理,综合性的介绍几款表格组件的 ...

  6. Winform界面中实现通用工具栏按钮的事件处理

    在一个给客户做的项目中,界面要求修改增加通用工具栏按钮的事件处理,也就是在主界面中放置几个固定的功能操作按钮,打开不同的页面的时候,实现对应页面的功能处理,这种和我标准的界面处理方式有所不同,标准的列 ...

  7. RDIFramework.NET V3.3 WinForm版新增订单管理主从表事例

    功能描述 无论什么系统,除了常规的单表处理外,主从表的应用都是非常普遍的,RDIFramework.NET V3.3 WinForm版本中新增了一个主从表的事例供大家参考.主从表的界面设计大同小异,主 ...

  8. iOS 11开发教程(十三)iOS11应用编辑界面添加视图

    iOS 11开发教程(十三)iOS11应用编辑界面添加视图 在iOS中添加视图的方式有两种:一种是使用编辑界面添加视图:另一种是使用代码添加视图.以下是这两个方式的详细介绍. 1.编辑界面添加视图 使 ...

  9. iOS 11开发教程(六)iOS11Main.storyboard文件编辑界面

    iOS 11开发教程(六)iOS11Main.storyboard文件编辑界面 在1.2.2小节中提到过编辑界面(Interface builder),编辑界面是用来设计用户界面的,单击打开Main. ...

随机推荐

  1. 【转载】jQuery全屏滚动插件fullPage.js

    文章转载自dowebok http://www.dowebok.com/ 原文链接:http://www.dowebok.com/77.html 简介 如今我们经常能见到全屏网站,尤其是国外网站.这些 ...

  2. Android 性能优化概念(1)

    http://www.open-open.com/lib/view/open1421723359718.html#_label0 阅读目录 0)Render Performance 1)Underst ...

  3. Cocos2d-x Lua游戏开发Mac环境搭建以及一点点感悟

    接触Cocos2d-x 最近由于公司项目的需要,自己开始接触Cocos,开始做一些简单的轻量级的游戏,以前没有接触过这一块的东西,也是借助这个机会学习一下游戏的开发,由于以前自己接触的全都是iOS和A ...

  4. A low-cost wear-leveling algorithm for block-mappingsolid-state disks

    [] Li-Pin Chang,Li-Chun Huang.A low-cost wear-leveling algorithm for block-mapping solid-state disks ...

  5. 博客收藏--sailing的博客

    http://blog.sina.com.cn/sailingxr free:这个博客主页的内容不错 PC的足迹 arm与x86 浅谈PCIe体系架构 浅谈cache memory

  6. 80端口被系统服务【kernel&System】占用解决方案

    netstat -ano | findstr port    //查看端口占用情况 tasklist | findstr port   //查看端口被占用的具体服务名 运行net stop http ...

  7. LINUX 笔记-grep命令

    grep [-acinv] [--color=auto] '查找字符串' filename 它的常用参数如下: -a :将binary文件以text文件的方式查找数据 -c :计算找到'查找字符串'的 ...

  8. 微信公众号支付|微信H5支付|微信扫码支付|小程序支付|APP微信支付解决方案总结

    最近负责的一些项目开发,都用到了微信支付(微信公众号支付.微信H5支付.微信扫码支付.APP微信支付).在开发的过程中,在调试支付的过程中,或多或少都遇到了一些问题,今天总结下,分享,留存. 先说注意 ...

  9. 别指望一文读懂Java并发之从一个线程开始

    Understanding concurrent programming is on the same order of difficulty as understanding object-orie ...

  10. url 地址处理(截取,参数等)

    function hrefObj() { var localhref = window.location.href; var localarr = localhref.split('?')[1].sp ...