1. 程式人生 > >在GridControl表格控件中實現多層級主從表數據的展示

在GridControl表格控件中實現多層級主從表數據的展示

其他 顯示數據 oid tar mdi 希望 運行 desc .com

在一些應用場景中,我們需要實現多層級的數據表格顯示,如常規的二級主從表數據展示,甚至也有多個層級展示的需求,那麽我們如何通過DevExpress的GridControl控表格件實現這種業務需求呢?本篇隨筆基於這個需求,對二級、三級的主從表數據進行展示,從而揭開對多層級數據展示的神秘面紗。

1、二級主從表數據展示

主從表數據,我們知道,一個主表記錄裏面關聯有多條明細從表記錄,在數據定義的層次上我們體現如下所示。

先定義一個實體類信息作為載體。

    /// <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 List<DetailInfo> Detail2List { get; set; } }

這個是我們使用繼承關系簡化了信息的定義,就是這個實體類包含主表信息外,還包含一個列表集合,屬於從表數據的。

有了這些數據的定義,我們構建一些測試的數據,如下所示。

            //創建測試數據
            var result = new Detail2Result()
            {
                Name = "測試",
                Description = "描述內容",
                Detail2List = new List<DetailInfo>()
                {
                    new DetailInfo()
                    {
                        Name = "111測試",
                        Description = "111描述內容"
                    },
                    new DetailInfo()
                    {
                        Name = "222測試",
                        Description = "222描述內容"
                    },
                    new DetailInfo()
                    {
                        Name = "333測試",
                        Description = "333描述內容"
                    }
                }
            };

            //構造一個記錄的集合
            var list = new List<Detail2Result>() { 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 List<DetailInfo>()
                {
                    new DetailInfo()
                    {
                        Name = "111測試",
                        Description = "111描述內容"
                    },
                    new DetailInfo()
                    {
                        Name = "222測試",
                        Description = "222描述內容"
                    },
                    new DetailInfo()
                    {
                        Name = "333測試",
                        Description = "333描述內容"
                    }
                }
            };

            //構造一個記錄的集合
            var list = new List<Detail2Result>() { result };

            //綁定數據源
            this.gridControl1.DataSource = list;
        }

        private void FrmTestDetails_Load(object sender, EventArgs e)
        {
            BindData();
        }

我們來運行下完成的程序界面,可以看到例子的效果界面如下所示。

技術分享圖片

我們可以看到數據記錄是有樹形節點的,展開就可以看到明細記錄了,這個就是我們這裏介紹的二級主從表數據的展示效果。

2、三級主從表數據展示

上面介紹了二級主從表的數據展示,其實GridControl可以用於展示三級以及更多層級的數據展示,只要你的數據設計合理,就可實現多層級的正確展示的。

本小節介紹三級的主從表數據展示,和二級數據展示類似,不過我們進一步實現了多層級的處理而已。

我們在二級層次的數據上定義了一個三級層次的數據實體類,如下所示。

    /// <summary>
    /// 二級層次的列表
    /// </summary>
    public class Detail2Result : DetailInfo
    {
        public List<DetailInfo> Detail2List { get; set; }
    }

    /// <summary>
    /// 三級層次的列表
    /// </summary>
    public class Detail3Result : DetailInfo
    {
        public List<Detail2Result> Detail3List { get; set; }
    }

三級層次的測試數據初始化如下所示:

            //創建測試數據
            var result = new Detail3Result()
            {
                Name = "測試11",
                Description = "描述內容11",
                //二級列表
                Detail3List = new List<Detail2Result>()
                {
                    new Detail2Result()
                    {
                        Name = "測試22",
                        Description = "描述內容22",
                             
                        //三級列表
                        Detail2List = new List<DetailInfo>() 
                        {
                            new DetailInfo()
                            {
                                Name = "31測試",
                                Description = "31描述內容"
                            },
                            new DetailInfo()
                            {
                                Name = "32測試",
                                Description = "32描述內容"
                            },
                            new DetailInfo()
                            {
                                Name = "33測試",
                                Description = "33描述內容"
                            }
                        }
                    }
                }
            };

            //構造一個記錄的集合
            var list = new List<Detail3Result>() { 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 List<Detail2Result>()
                {
                    new Detail2Result()
                    {
                        Name = "測試22",
                        Description = "描述內容22",
                             
                        //三級列表
                        Detail2List = new List<DetailInfo>() 
                        {
                            new DetailInfo()
                            {
                                Name = "31測試",
                                Description = "31描述內容"
                            },
                            new DetailInfo()
                            {
                                Name = "32測試",
                                Description = "32描述內容"
                            },
                            new DetailInfo()
                            {
                                Name = "33測試",
                                Description = "33描述內容"
                            }
                        }
                    }
                }
            };

            //構造一個記錄的集合
            var list = new List<Detail3Result>() { result };

            //綁定數據源
            this.gridControl1.DataSource = list;
        }

以上就是三級層次的關系處理,如果我們理解了,其他更多層級的數據展示也是依照這個規則,增加節點和視圖即可,原理一樣。

案例的效果如下所示。

技術分享圖片

3、利用分頁控件實現數據的展示

上面的兩個案例是基於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實現數據的主從關系的處理,可以實現多層級的展示,希望這些案例能夠對你展示數據有所幫助。

在GridControl表格控件中實現多層級主從表數據的展示