在一些应用场景中,我们需要实现多层级的数据表格显示,如常规的二级主从表数据展示,甚至也有多个层级展示的需求,那么我们如何通过DevExpress的GridControl控表格件实现这种业务需求呢?本篇随笔基于这个需求,对二级、三级的主从表数据进行展示,从而揭开对多层级数据展示的神秘面纱。

1、二级主从表数据展示

主从表数据,我们知道,一个主表记录里面关联有多条明细从表记录,在数据定义的层次上我们体现如下所示。

先定义一个实体类信息作为载体。

    /// <summary>
    ///记录基础信息/// </summary>
    public classDetailInfo
{
publicDetailInfo()
{
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 classDetail2Result : DetailInfo
{
public List<DetailInfo> Detail2List { get; set; }
}

这个是我们使用继承关系简化了信息的定义,就是这个实体类包含主表信息外,还包含一个列表集合,属于从表数据的。

有了这些数据的定义,我们构建一些测试的数据,如下所示。

            //创建测试数据
            var result = newDetail2Result()
{
Name
= "测试",
Description
= "描述内容",
Detail2List
= new List<DetailInfo>()
{
newDetailInfo()
{
Name
= "666666测试",
Description
= "666666描述内容"},newDetailInfo()
{
Name
= "222测试",
Description
= "222描述内容"},newDetailInfo()
{
Name
= "333测试",
Description
= "333描述内容"}
}
};
//构造一个记录的集合 var list = new List<Detail2Result>() { result };

这样我们就构建了一个主表从表记录的数据源,可以用于表格控件的绑定的了。

首先我们在界面上创建一个空白的窗体用于演示,并在窗体上增加一个GridControl控件用于展示主从表的数据,如下界面所示。

然后,我们可以通过代码创建我们需要的视图信息,如创建主表的GridView显示如下所示。

        /// <summary>
        ///创建第一个视图/// </summary>
        private voidCreateGridView()
{
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 voidCreateLevelView()
{
var grv = this.gridView1;var gridControl = this.gridControl1;//创建一个从表的GridView对象 grv2 = newGridView();
grv2.ViewCaption
= "记录明细";
grv2.Name
= "grv2";
grv2.GridControl
=gridControl;//构建GridLevelNode并添加到LevelTree集合里面 var node = newGridLevelNode();
node.LevelTemplate
=grv2;
node.RelationName
= "Detail2List";//这里对应集合的属性名称 gridControl.LevelTree.Nodes.AddRange(newGridLevelNode[]
{
node
});
//添加对应的视图集合显示 gridControl.ViewCollection.Clear();
gridControl.ViewCollection.AddRange(
newBaseView[] { 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 = newGridLevelNode();
node.LevelTemplate
=grv2;
node.RelationName
= "Detail2List";//这里对应集合的属性名称 gridControl.LevelTree.Nodes.AddRange(newGridLevelNode[]
{
node
});

首先是创建一个节点,然后指定它的 LevelTemplate 为我们新建的GridView,并且他的子集合对象名称为 Detail2List ,最后把这个节点的信息加入到 gridControl.LevelTree.Nodes 里面就可以了,其他的代码就和第一步差不多,指定显示的列和中文显示名称即可。

还有就是我们需要把创建的GridView 加入到指定的集合里面。

            //添加对应的视图集合显示
gridControl.ViewCollection.Clear();
gridControl.ViewCollection.AddRange(
new BaseView[] { grv, grv2 });

到这里基本上就是大功告成了,剩下的就是数据的绑定处理了。前面我们已经介绍了实体类的准备工作和创建测试数据的代码,那么我们这里沿用上面的代码进行数据的绑定就可以了。如下代码所示。

        /// <summary>
        ///绑定数据源/// </summary>
        private voidBindData()
{
//创建测试数据 var result = newDetail2Result()
{
Name
= "测试",
Description
= "描述内容",
Detail2List
= new List<DetailInfo>()
{
newDetailInfo()
{
Name
= "666666测试",
Description
= "666666描述内容"},newDetailInfo()
{
Name
= "222测试",
Description
= "222描述内容"},newDetailInfo()
{
Name
= "333测试",
Description
= "333描述内容"}
}
};
//构造一个记录的集合 var list = new List<Detail2Result>() { result };//绑定数据源 this.gridControl1.DataSource =list;
}
private void FrmTestDetails_Load(objectsender, EventArgs e)
{
BindData();
}

我们来运行下完成的程序界面,可以看到例子的效果界面如下所示。

我们可以看到数据记录是有树形节点的,展开就可以看到明细记录了,这个就是我们这里介绍的二级主从表数据的展示效果。

2、三级主从表数据展示

上面介绍了二级主从表的数据展示,其实GridControl可以用于展示三级以及更多层级的数据展示,只要你的数据设计合理,就可实现多层级的正确展示的。

本小节介绍三级的主从表数据展示,和二级数据展示类似,不过我们进一步实现了多层级的处理而已。

我们在二级层次的数据上定义了一个三级层次的数据实体类,如下所示。

    /// <summary>
    ///二级层次的列表/// </summary>
    public classDetail2Result : DetailInfo
{
public List<DetailInfo> Detail2List { get; set; }
}
/// <summary> ///三级层次的列表/// </summary> public classDetail3Result : DetailInfo
{
public List<Detail2Result> Detail3List { get; set; }
}

三级层次的测试数据初始化如下所示:

            //创建测试数据
            var result = newDetail3Result()
{
Name
= "测试11",
Description
= "描述内容11",//二级列表 Detail3List = new List<Detail2Result>()
{
newDetail2Result()
{
Name
= "测试22",
Description
= "描述内容22",//三级列表 Detail2List = new List<DetailInfo>()
{
newDetailInfo()
{
Name
= "31测试",
Description
= "31描述内容"},newDetailInfo()
{
Name
= "32测试",
Description
= "32描述内容"},newDetailInfo()
{
Name
= "33测试",
Description
= "33描述内容"}
}
}
}
};
//构造一个记录的集合 var list = new List<Detail3Result>() { result };

和二级层次的处理步骤类似,我们先创建主表的信息展示,如下所示。

        /// <summary>
        ///创建第一个视图/// </summary>
        private voidCreateGridView()
{
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 voidCreateLevelView()
{
var grv = this.gridView1;var gridControl = this.gridControl1;//创建一个二级从表的GridView对象 grv2 = newGridView();
grv2.ViewCaption
= "记录明细";
grv2.Name
= "grv2";
grv2.GridControl
=gridControl;//创建一个三级从表的GridView对象 grv3 = newGridView();
grv3.ViewCaption
= "记录明细2";
grv3.Name
= "grv3";
grv3.GridControl
= gridControl;

这样我们相当于创建多两个(总共三个GridView对象)用于展示数据列表。

接着最为关键的是主从关系的节点,我们可以简单的理解他的Node节点和我们树形列表的Node处理方式类似即可。

            //构建GridLevelNode
            var topNode = newGridLevelNode();
topNode.LevelTemplate
= grv2; //这里是对应的视图 topNode.RelationName = "Detail3List"; //这里对应集合的属性名称//构建GridLevelNode var secondNode = newGridLevelNode();
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(
newBaseView[] { 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 voidCreateLevelView()
{
var grv = this.gridView1;var gridControl = this.gridControl1;//创建一个二级从表的GridView对象 grv2 = newGridView();
grv2.ViewCaption
= "记录明细";
grv2.Name
= "grv2";
grv2.GridControl
=gridControl;//创建一个三级从表的GridView对象 grv3 = newGridView();
grv3.ViewCaption
= "记录明细2";
grv3.Name
= "grv3";
grv3.GridControl
=gridControl;//构建GridLevelNode var topNode = newGridLevelNode();
topNode.LevelTemplate
= grv2; //这里是对应的视图 topNode.RelationName = "Detail3List"; //这里对应集合的属性名称//构建GridLevelNode var secondNode = newGridLevelNode();
secondNode.LevelTemplate
= grv3; //这里是对应的视图 secondNode.RelationName = "Detail2List";//这里对应集合的属性名称//需要添加节点的层级关系,类似Tree节点处理 topNode.Nodes.Add(secondNode);//最后添加节点到集合里面 gridControl.LevelTree.Nodes.Add(topNode);//添加对应的视图集合显示 gridControl.ViewCollection.Clear();
gridControl.ViewCollection.AddRange(
newBaseView[] { 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 classFrmTestDetails2 : BaseForm
{
publicFrmTestDetails2()
{
InitializeComponent();

CreateGridView();
CreateLevelView();
}

最后就是数据源的绑定操作了,这个利用前面介绍过的准备数据即可。

        private void FrmTestDetails2_Load(objectsender, EventArgs e)
{
BindData();
}
/// <summary> ///绑定数据源/// </summary> private voidBindData()
{
//创建测试数据 var result = newDetail3Result()
{
Name
= "测试11",
Description
= "描述内容11",//二级列表 Detail3List = new List<Detail2Result>()
{
newDetail2Result()
{
Name
= "测试22",
Description
= "描述内容22",//三级列表 Detail2List = new List<DetailInfo>()
{
newDetailInfo()
{
Name
= "31测试",
Description
= "31描述内容"},newDetailInfo()
{
Name
= "32测试",
Description
= "32描述内容"},newDetailInfo()
{
Name
= "33测试",
Description
= "33描述内容"}
}
}
}
};
//构造一个记录的集合 var list = new List<Detail3Result>() { result };//绑定数据源 this.gridControl1.DataSource =list;
}

以上就是三级层次的关系处理,如果我们理解了,其他更多层级的数据展示也是依照这个规则,增加节点和视图即可,原理一样。

案例的效果如下所示。

3、利用分页控件实现数据的展示

上面的两个案例是基于DevExpress的内置表格控件GridControl进行处理的,我们在Winform框架的开发过程中,往往为了效率和分页方便,一般都是使用分页控件来展示数据的,那么利用分页控件实现多层级的数据展示是如何的呢?

其实基本步骤也是差不多的,只是主表视图使用分页控件即可,如下所示。

    /// <summary>
    ///数据指定的主从表展示/// </summary>    
    public partial classFrmDictTypeMasterDetail : BaseDock
{
publicFrmDictTypeMasterDetail()
{
InitializeComponent();

InitDictItem();
this.winGridViewPager1.OnPageChanged += newEventHandler(winGridViewPager1_OnPageChanged);this.winGridViewPager1.OnStartExport += newEventHandler(winGridViewPager1_OnStartExport); this.winGridViewPager1.OnDeleteSelected += newEventHandler(winGridViewPager1_OnDeleteSelected);this.winGridViewPager1.OnRefresh += newEventHandler(winGridViewPager1_OnRefresh);this.winGridViewPager1.AppendedMenu = this.contextMenuStrip1;this.winGridViewPager1.ShowLineNumber = true;this.winGridViewPager1.BestFitColumnWith = false;//是否设置为自动调整宽度,false为不设置 this.winGridViewPager1.gridView1.DataSourceChanged += newEventHandler(gridView1_DataSourceChanged);this.winGridViewPager1.gridView1.CustomColumnDisplayText += newDevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(gridView1_CustomColumnDisplayText);this.winGridViewPager1.gridView1.RowCellStyle += newDevExpress.XtraGrid.Views.Grid.RowCellStyleEventHandler(gridView1_RowCellStyle);CreateLevelView();
RegisterEvent();
}

GridView grv2
= null;private voidCreateLevelView()
{
var grv = this.winGridViewPager1.GridView1;var gridControl = this.winGridViewPager1.gridControl1;//创建一个从表的GridView对象 grv2 = newGridView();
grv2.ViewCaption
= "记录明细";
grv2.Name
= "grv2";
grv2.GridControl
=gridControl;//构建GridLevelNode并添加到LevelTree集合里面 var node = newGridLevelNode();
node.LevelTemplate
=grv2;
node.RelationName
= "Children";
gridControl.LevelTree.Nodes.AddRange(
newGridLevelNode[]
{
node
});

gridControl.ViewCollection.Clear();
gridControl.ViewCollection.AddRange(
newBaseView[] { 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实现数据的主从关系的处理,可以实现多层级的展示,希望这些案例能够对你展示数据有所帮助。

标签: none

添加新评论