在一些应用场景中我们需要实现多层级的数据表格显示如常规的二级主从表数据展示甚至也有多个层级展示的需求那么我们如何通过DevExpress的GridControl控表格件实现这种业务需求呢本篇随笔基于这个需求对二级、三级的主从表数据进行展示从而揭开对多层级数据展示的神秘面纱。PS给大家推荐这个WinForm应用界面开发组件——DevExpress WinForms它能完美构建流畅、美观且易于使用的应用程序无论是Office风格的界面还是分析处理大批量的业务数据它都能轻松胜任DevExpress新旧版本帮助文档获取可点击这篇文章查看——《界面控件DevExpress v26.1帮助文档大全CHM版本》二级主从表数据展示主从表数据我们知道一个主表记录里面关联有多条明细从表记录在数据定义的层次上我们体现如下所示。先定义一个实体类信息作为载体。/// summary /// 记录基础信息 /// /summary public class DetailInfo { public DetailInfo() { this.ID Guid.NewGuid().ToString(); } /// summary /// ID标识 /// /summary public string ID { get; set; } /// summary /// 名称 /// /summary public string Name { get; set; } /// summary /// 描述信息 /// /summary public string Description { get; set; } }然后主从表的数据实体类就是除了包含这些信息外再包含一个子列表列表信息不一定是同一个实体类如下所示。/// summary /// 二级层次的列表 /// /summary public class Detail2Result : DetailInfo { public ListDetailInfo Detail2List { get; set; } }这个是我们使用继承关系简化了信息的定义就是这个实体类包含主表信息外还包含一个列表集合属于从表数据的。有了这些数据的定义我们构建一些测试的数据如下所示。//创建测试数据 var result new Detail2Result() { Name 测试, Description 描述内容, Detail2List new ListDetailInfo() { new DetailInfo() { Name 111测试, Description 111描述内容 }, new DetailInfo() { Name 222测试, Description 222描述内容 }, new DetailInfo() { Name 333测试, Description 333描述内容 } } }; //构造一个记录的集合 var list new ListDetail2Result() { result };这样我们就构建了一个主表从表记录的数据源可以用于表格控件的绑定的了。首先我们在界面上创建一个空白的窗体用于演示并在窗体上增加一个GridControl控件用于展示主从表的数据如下界面所示。然后我们可以通过代码创建我们需要的视图信息如创建主表的GridView显示如下所示。/// summary /// 创建第一个视图 /// /summary private void CreateGridView() { var grv this.gridView1; //创建从表显示的列 grv.Columns.Clear(); grv.CreateColumn(ID, ID);//.Visible false; grv.CreateColumn(Name, 名称); grv.CreateColumn(Description, 描述内容); grv.OptionsBehavior.ReadOnly false; grv.OptionsBehavior.Editable true; }很简单我们创建几个列并指定它的Caption中文显示属性就可以了然后我们接着还需要创建从表的GridView显示数据这个是这篇随笔的关键。具体的代码一次性贴出来如下所示。GridView grv2 null; /// summary /// 创建第二个视图 /// /summary private void CreateLevelView() { var grv this.gridView1; var gridControl this.gridControl1; //创建一个从表的GridView对象 grv2 new GridView(); grv2.ViewCaption 记录明细; grv2.Name grv2; grv2.GridControl gridControl; //构建GridLevelNode并添加到LevelTree集合里面 var node new GridLevelNode(); node.LevelTemplate grv2; node.RelationName Detail2List;//这里对应集合的属性名称 gridControl.LevelTree.Nodes.AddRange(new GridLevelNode[] { node }); //添加对应的视图集合显示 gridControl.ViewCollection.Clear(); gridControl.ViewCollection.AddRange(new BaseView[] { grv, grv2 }); //创建从表显示的列 grv2.Columns.Clear(); grv2.CreateColumn(ID, ID); grv2.CreateColumn(Name, 名称); grv2.CreateColumn(Description, 描述内容); //设置非只读、可编辑 grv2.OptionsBehavior.ReadOnly false; grv2.OptionsBehavior.Editable true; }我们这里注意到 GridLevelNode 对象它是我们主从表节点的关键信息我们需要了解下面部分的代码//构建GridLevelNode并添加到LevelTree集合里面 var node new GridLevelNode(); node.LevelTemplate grv2; node.RelationName Detail2List;//这里对应集合的属性名称 gridControl.LevelTree.Nodes.AddRange(new GridLevelNode[] { node });首先是创建一个节点然后指定它的 LevelTemplate 为我们新建的GridView并且他的子集合对象名称为 Detail2List 最后把这个节点的信息加入到 gridControl.LevelTree.Nodes 里面就可以了其他的代码就和第一步差不多指定显示的列和中文显示名称即可。还有就是我们需要把创建的GridView 加入到指定的集合里面。//添加对应的视图集合显示 gridControl.ViewCollection.Clear(); gridControl.ViewCollection.AddRange(new BaseView[] { grv, grv2 });到这里基本上就是大功告成了剩下的就是数据的绑定处理了。前面我们已经介绍了实体类的准备工作和创建测试数据的代码那么我们这里沿用上面的代码进行数据的绑定就可以了。如下代码所示。/// summary /// 绑定数据源 /// /summary private void BindData() { //创建测试数据 var result new Detail2Result() { Name 测试, Description 描述内容, Detail2List new ListDetailInfo() { new DetailInfo() { Name 111测试, Description 111描述内容 }, new DetailInfo() { Name 222测试, Description 222描述内容 }, new DetailInfo() { Name 333测试, Description 333描述内容 } } }; //构造一个记录的集合 var list new ListDetail2Result() { result }; //绑定数据源 this.gridControl1.DataSource list; } private void FrmTestDetails_Load(object sender, EventArgs e) { BindData(); }我们来运行下完成的程序界面可以看到例子的效果界面如下所示。我们可以看到数据记录是有树形节点的展开就可以看到明细记录了这个就是我们这里介绍的二级主从表数据的展示效果。三级主从表数据展示上面介绍了二级主从表的数据展示其实GridControl可以用于展示三级以及更多层级的数据展示只要你的数据设计合理就可实现多层级的正确展示的。本小节介绍三级的主从表数据展示和二级数据展示类似不过我们进一步实现了多层级的处理而已。我们在二级层次的数据上定义了一个三级层次的数据实体类如下所示。/// summary /// 二级层次的列表 /// /summary public class Detail2Result : DetailInfo { public ListDetailInfo Detail2List { get; set; } } /// summary /// 三级层次的列表 /// /summary public class Detail3Result : DetailInfo { public ListDetail2Result Detail3List { get; set; } }三级层次的测试数据初始化如下所示//创建测试数据 var result new Detail3Result() { Name 测试11, Description 描述内容11, //二级列表 Detail3List new ListDetail2Result() { new Detail2Result() { Name 测试22, Description 描述内容22, //三级列表 Detail2List new ListDetailInfo() { new DetailInfo() { Name 31测试, Description 31描述内容 }, new DetailInfo() { Name 32测试, Description 32描述内容 }, new DetailInfo() { Name 33测试, Description 33描述内容 } } } } }; //构造一个记录的集合 var list new ListDetail3Result() { result };和二级层次的处理步骤类似我们先创建主表的信息展示如下所示。/// summary /// 创建第一个视图 /// /summary private void CreateGridView() { var grv this.gridView1; var gridControl this.gridControl1; //创建从表显示的列 grv.Columns.Clear(); grv.CreateColumn(ID, ID);//.Visible false; grv.CreateColumn(Name, 名称); grv.CreateColumn(Description, 描述内容); grv.OptionsBehavior.ReadOnly false; grv.OptionsBehavior.Editable true; }然后着手创建二级、三级的列表信息展示GridView grv2 null; GridView grv3 null; /// summary /// 创建第二个视图 /// /summary private void CreateLevelView() { var grv this.gridView1; var gridControl this.gridControl1; //创建一个二级从表的GridView对象 grv2 new GridView(); grv2.ViewCaption 记录明细; grv2.Name grv2; grv2.GridControl gridControl; //创建一个三级从表的GridView对象 grv3 new GridView(); grv3.ViewCaption 记录明细2; grv3.Name grv3; grv3.GridControl gridControl;这样我们相当于创建多两个总共三个GridView对象用于展示数据列表。接着最为关键的是主从关系的节点我们可以简单的理解他的Node节点和我们树形列表的Node处理方式类似即可。//构建GridLevelNode var topNode new GridLevelNode(); topNode.LevelTemplate grv2; //这里是对应的视图 topNode.RelationName Detail3List; //这里对应集合的属性名称 //构建GridLevelNode var secondNode new GridLevelNode(); secondNode.LevelTemplate grv3; //这里是对应的视图 secondNode.RelationName Detail2List;//这里对应集合的属性名称 //需要添加节点的层级关系类似Tree节点处理 topNode.Nodes.Add(secondNode); //最后添加节点到集合里面 gridControl.LevelTree.Nodes.Add(topNode);通过定义两个GridLevelNode然后指定他们的Node关系 topNode.Nodes.Add(secondNode) 这样我们就可以很清晰的关联起来它们的节点关系了。最后是把我们创建的几个视图加入到集合里面并设定一些关系即可。//添加对应的视图集合显示 gridControl.ViewCollection.Clear(); gridControl.ViewCollection.AddRange(new BaseView[] { grv, grv2, grv3 }); //创建从表显示的列 grv2.Columns.Clear(); grv2.CreateColumn(ID, ID); grv2.CreateColumn(Name, 名称); grv2.CreateColumn(Description, 描述内容); //创建从表显示的列 grv3.Columns.Clear(); grv3.CreateColumn(ID, ID); grv3.CreateColumn(Name, 名称); grv3.CreateColumn(Description, 描述内容); //设置非只读、可编辑 grv2.OptionsBehavior.ReadOnly false; grv2.OptionsBehavior.Editable true; //设置非只读、可编辑 grv3.OptionsBehavior.ReadOnly false; grv3.OptionsBehavior.Editable true; 整个部分的代码如下所示。 GridView grv2 null; GridView grv3 null; /// summary /// 创建第二个视图 /// /summary private void CreateLevelView() { var grv this.gridView1; var gridControl this.gridControl1; //创建一个二级从表的GridView对象 grv2 new GridView(); grv2.ViewCaption 记录明细; grv2.Name grv2; grv2.GridControl gridControl; //创建一个三级从表的GridView对象 grv3 new GridView(); grv3.ViewCaption 记录明细2; grv3.Name grv3; grv3.GridControl gridControl; //构建GridLevelNode var topNode new GridLevelNode(); topNode.LevelTemplate grv2; //这里是对应的视图 topNode.RelationName Detail3List; //这里对应集合的属性名称 //构建GridLevelNode var secondNode new GridLevelNode(); secondNode.LevelTemplate grv3; //这里是对应的视图 secondNode.RelationName Detail2List;//这里对应集合的属性名称 //需要添加节点的层级关系类似Tree节点处理 topNode.Nodes.Add(secondNode); //最后添加节点到集合里面 gridControl.LevelTree.Nodes.Add(topNode); //添加对应的视图集合显示 gridControl.ViewCollection.Clear(); gridControl.ViewCollection.AddRange(new BaseView[] { grv, grv2, grv3 }); //创建从表显示的列 grv2.Columns.Clear(); grv2.CreateColumn(ID, ID); grv2.CreateColumn(Name, 名称); grv2.CreateColumn(Description, 描述内容); //创建从表显示的列 grv3.Columns.Clear(); grv3.CreateColumn(ID, ID); grv3.CreateColumn(Name, 名称); grv3.CreateColumn(Description, 描述内容); //设置非只读、可编辑 grv2.OptionsBehavior.ReadOnly false; grv2.OptionsBehavior.Editable true; //设置非只读、可编辑 grv3.OptionsBehavior.ReadOnly false; grv3.OptionsBehavior.Editable true; } 也就是我们在窗体初始化的时候创建它们的视图关系即可如下代码所示。 /// summary /// 测试三级主从明细列表 /// /summary public partial class FrmTestDetails2 : BaseForm { public FrmTestDetails2() { InitializeComponent(); CreateGridView(); CreateLevelView(); }最后就是数据源的绑定操作了这个利用前面介绍过的准备数据即可。private void FrmTestDetails2_Load(object sender, EventArgs e) { BindData(); } /// summary /// 绑定数据源 /// /summary private void BindData() { //创建测试数据 var result new Detail3Result() { Name 测试11, Description 描述内容11, //二级列表 Detail3List new ListDetail2Result() { new Detail2Result() { Name 测试22, Description 描述内容22, //三级列表 Detail2List new ListDetailInfo() { new DetailInfo() { Name 31测试, Description 31描述内容 }, new DetailInfo() { Name 32测试, Description 32描述内容 }, new DetailInfo() { Name 33测试, Description 33描述内容 } } } } }; //构造一个记录的集合 var list new ListDetail3Result() { result }; //绑定数据源 this.gridControl1.DataSource list; }以上就是三级层次的关系处理如果我们理解了其他更多层级的数据展示也是依照这个规则增加节点和视图即可原理一样。案例的效果如下所示。利用分页控件实现数据的展示上面的两个案例是基于DevExpress的内置表格控件GridControl进行处理的我们在Winform框架的开发过程中往往为了效率和分页方便一般都是使用分页控件来展示数据的那么利用分页控件实现多层级的数据展示是如何的呢其实基本步骤也是差不多的只是主表视图使用分页控件即可如下所示。/// summary /// 数据指定的主从表展示 /// /summary public partial class FrmDictTypeMasterDetail : BaseDock { public FrmDictTypeMasterDetail() { InitializeComponent(); InitDictItem(); this.winGridViewPager1.OnPageChanged new EventHandler(winGridViewPager1_OnPageChanged); this.winGridViewPager1.OnStartExport new EventHandler(winGridViewPager1_OnStartExport); this.winGridViewPager1.OnDeleteSelected new EventHandler(winGridViewPager1_OnDeleteSelected); this.winGridViewPager1.OnRefresh new EventHandler(winGridViewPager1_OnRefresh); this.winGridViewPager1.AppendedMenu this.contextMenuStrip1; this.winGridViewPager1.ShowLineNumber true; this.winGridViewPager1.BestFitColumnWith false;//是否设置为自动调整宽度false为不设置 this.winGridViewPager1.gridView1.DataSourceChanged new EventHandler(gridView1_DataSourceChanged); this.winGridViewPager1.gridView1.CustomColumnDisplayText new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(gridView1_CustomColumnDisplayText); this.winGridViewPager1.gridView1.RowCellStyle new DevExpress.XtraGrid.Views.Grid.RowCellStyleEventHandler(gridView1_RowCellStyle); CreateLevelView(); RegisterEvent(); } GridView grv2 null; private void CreateLevelView() { var grv this.winGridViewPager1.GridView1; var gridControl this.winGridViewPager1.gridControl1; //创建一个从表的GridView对象 grv2 new GridView(); grv2.ViewCaption 记录明细; grv2.Name grv2; grv2.GridControl gridControl; //构建GridLevelNode并添加到LevelTree集合里面 var node new GridLevelNode(); node.LevelTemplate grv2; node.RelationName Children; gridControl.LevelTree.Nodes.AddRange(new GridLevelNode[] { node }); gridControl.ViewCollection.Clear(); gridControl.ViewCollection.AddRange(new BaseView[] { grv, grv2 }); //创建从表显示的列 grv2.Columns.Clear(); grv2.CreateColumn(ID, ID).Visible false; //标识行的关键字可用于删除处理 grv2.CreateColumn(DictType_ID, DictType_ID).Visible false;//创建一个字段隐藏的存储记录 grv2.CreateColumn(Name, 项目名称); grv2.CreateColumn(Value, 项目值); grv2.CreateColumn(Seq, 排序); grv2.CreateColumn(Remark, 备注); grv2.OptionsBehavior.ReadOnly false; grv2.OptionsBehavior.Editable true; grv2.DataSourceChanged grv2_DataSourceChanged; }以上就是基于GridControl实现数据的主从关系的处理可以实现多层级的展示希望这些案例能够对你展示数据有所帮助。本文转载自博客园 - 伍华聪