65.9K
CodeProject 正在变化。 阅读更多。
Home

Windows Forms C# 中的嵌套 DataGridView

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.78/5 (48投票s)

2015年1月20日

CPOL

5分钟阅读

viewsIcon

175882

downloadIcon

16252

适用于 Winforms 的嵌套或主从或分层 DataGridView

引言

在我上一篇文章中,我解释了如何使用 C# 创建一个 DataGridView 辅助类。

我扩展了 DataGridView 辅助类来创建一个嵌套的 DataGridView。几天前,一位 CodeProject 会员询问如何在 WinForms 中创建嵌套的或主从详情或分层 DataGridView。我开始在 Google 上搜索,但没有找到任何关于嵌套 DataGridView 的结果。我开始着手创建一个嵌套 DataGridView 的示例程序,这应该对所有人都有用。因此,我创建了一个嵌套 DataGridView,您可以在本文开头提供的链接中找到源代码。我的目标是为用户创建一个简单易懂的程序。用户可以下载代码并根据自己的需求进行定制。

为什么我们需要嵌套或分层 DataGridView

在实际项目中,例如订单管理、生产管理等,我们需要以分层结构显示数据。

例如,让我们以一家餐厅的订单管理项目为例。假设有四个人去餐厅吃午餐。餐厅的服务员会给他们菜单卡,让他们选择要点的菜品。现在,在一张桌子旁,总共有四个人坐着。在餐厅管理中,通常所有桌子都会有一个唯一的桌子 ID 或名称。这四个人将从菜单卡中选择他们需要的菜品,并下单,以便为他们提供食物。在餐厅管理中,对于每个订单,我们将在订单主表中创建一个唯一的 ID,并在订单详情表中存储与该订单相关的所有项目详情。让我们看一个订单的示例结构。

为什么我们需要主表和详情表?

为了避免数据重复,我们可以使用主从详情表关系来存储数据。例如,每个订单会有一个服务员和一张桌子,所以如果我们不使用主从详情表关系,结果将如下所示:

在这里,我们可以看到订单号、桌子 ID、服务员姓名和订单日期被重复了。为了避免这些重复数据,我们将创建主表和详情表关系。请参阅下面的主表和详情表。

订单主表

在这里,我们可以看到重复的数据已存储在名为订单主表的单独表中。

订单详情表

在这里,我们可以看到订单的所有项目详情都在一个单独的表中。但是,在详情表中,我们使用了 Order NO 来与 Master 表建立关联。通过这种关联,我们可以合并这两个表并生成输出。

普通网格结果

结果可以显示而不使用分层网格输出。但我们必须如下所示显示重复的结果:

我们也可以合并相同的数据并如下表所示显示结果。但输出效果不太好,也不易于查看和理解。

现在让我们看看相同结果的分层输出。

现在这个最终结果看起来比之前所有都好多了。可以轻松查看所有记录的主表和详情。

这是我的分层 DataGridView 的示例输出。

与餐厅项目中的订单管理类似,我们将有账单主表和详情表、账户主表和详情表、商品主表和详情表、库存主表和详情表。在生产项目中,我们将有生产订单主表和订单详情表、成品入库主表和详情表、成品出库主表和详情表等。与此类似,在我们所有的实际项目中,我们将使用主从详情关系来显示我们的数据。

Using the Code

正如我所说,在这篇文章中,我使用并扩展了我的 DataGridView 辅助类来创建一个嵌套 DataGridView。您可以通过我的文章查看我的 DataGridView 辅助类的详细信息。

在我的 DGVhelper 类中,我添加了以下功能来创建嵌套网格:

  • ImageCoulmn (图片列)
  • DGVMasterGridClickEvents (主网格点击事件)
  • DGVDetailGridClickEvents (详情网格点击事件)

用户可以对主网格和详情网格使用所有事件,例如 CellClickCellContentClick 等。

我创建了两个单独的列表类来填充主表和详情结果。在窗体加载时,调用方法将详情添加到每个列表类中。

我使用我的 ShanuDGVHelper 类以编程方式(动态地)创建了主表和详情 DataGridView

主网格设置

在窗体加载时,我调用了此方法在运行时创建主 DataGridView

在我的代码中,我在每行之前添加了注释来解释其用途。

   // to generate Master Datagridview with your coding
        public void MasterGrid_Initialize()
        {
            //First generate the grid Layout Design
            Helper.ShanuDGVHelper.Layouts(Master_shanuDGV, Color.LightSteelBlue, 
            Color.AliceBlue, Color.WhiteSmoke, false, Color.SteelBlue, false, false, false);

            //Set Height ,width and add panel to your selected control
            Helper.ShanuDGVHelper.Generategrid
                   (Master_shanuDGV, pnlShanuGrid, 1000, 600, 10, 10);

            // Color Image Column creation
            Helper.ShanuDGVHelper.Templatecolumn(Master_shanuDGV, 
            ShanuControlTypes.ImageColumn, "img", "", "", true, 26, 
            DataGridViewTriState.True, DataGridViewContentAlignment.MiddleCenter, 
            DataGridViewContentAlignment.MiddleRight, Color.Transparent, null, 
            "", "", Color.Black);

            // BoundColumn creation
            Helper.ShanuDGVHelper.Templatecolumn(Master_shanuDGV, 
            ShanuControlTypes.BoundColumn, "Order_No", "Order NO", "Order NO", 
            true, 90, DataGridViewTriState.True, DataGridViewContentAlignment.MiddleLeft, 
            DataGridViewContentAlignment.MiddleCenter, Color.Transparent, null, 
            "", "", Color.Black);

            // BoundColumn creation
            Helper.ShanuDGVHelper.Templatecolumn(Master_shanuDGV, 
            ShanuControlTypes.BoundColumn, "Table_ID", "Table ID", "Table ID", 
            true, 80, DataGridViewTriState.True, DataGridViewContentAlignment.MiddleLeft, 
            DataGridViewContentAlignment.MiddleCenter, Color.Transparent, null, 
            "", "", Color.Black);

            // BoundColumn creation
            Helper.ShanuDGVHelper.Templatecolumn(Master_shanuDGV, 
            ShanuControlTypes.BoundColumn, "Description", "Description", "Description", 
            true, 320, DataGridViewTriState.True, DataGridViewContentAlignment.MiddleLeft, 
            DataGridViewContentAlignment.MiddleCenter, Color.Transparent, null, 
            "", "", Color.Black);

            // BoundColumn creation
            Helper.ShanuDGVHelper.Templatecolumn(Master_shanuDGV, 
            ShanuControlTypes.BoundColumn, "Order_DATE", "Order DATE", "Order DATE", 
            true, 140, DataGridViewTriState.True, DataGridViewContentAlignment.MiddleCenter, 
            DataGridViewContentAlignment.MiddleCenter, Color.Transparent, null, 
            "", "", Color.Black);

            // BoundColumn creation
            Helper.ShanuDGVHelper.Templatecolumn
            (Master_shanuDGV, ShanuControlTypes.BoundColumn, "Waiter_ID", 
            "Waiter_ID", "Waiter_ID", true, 120, DataGridViewTriState.True, 
            DataGridViewContentAlignment.MiddleLeft, 
            DataGridViewContentAlignment.MiddleCenter, Color.Transparent, null, 
            "", "", Color.Black);

            //Convert the List to DataTable
            DataTable detailTableList = ListtoDataTable
            (DataClass.OrderDetailBindClass.objDetailDGVBind);

            // Image Column Click Event - In  this method we create an event for 
            // cell click and we will display the Detail grid with result.

            objshanudgvHelper.DGVMasterGridClickEvents(Master_shanuDGV, 
            Detail_shanuDGV, Master_shanuDGV.Columns["img"].Index, 
            ShanuEventTypes.cellContentClick, ShanuControlTypes.ImageColumn, 
            detailTableList, "Order_No");
            
            // Bind data to DGV.
            Master_shanuDGV.DataSource = DataClass.OrderMasterBindClass.objMasterDGVBind;
        }

单元格点击事件

我调用了上面的方法来为主 DataGridView 创建一个单元格点击事件。

 // Image Column Click Event - In  this method we create an event for 
 // cell click and we will display the Detail grid with result.
 objshanudgvHelper.DGVMasterGridClickEvents(Master_shanuDGV, Detail_shanuDGV, 
 Master_shanuDGV.Columns["img"].Index, ShanuEventTypes.cellContentClick, 
 ShanuControlTypes.ImageColumn, detailTableList, "Order_No");

此事件将用于主网格图片点击事件。在此事件中,我将获取订单号并从 DataTabledetail 中过滤结果。将最终的 Dataview 结果显示到 Detail DataGridView

  public void DGVMasterGridClickEvents(DataGridView ShanuMasterDGV, 
  DataGridView ShanuDetailDGV, int columnIndexs, ShanuEventTypes eventtype, 
  ShanuControlTypes types,DataTable DetailTable,String FilterColumn)
        {
            MasterDGVs = ShanuMasterDGV;
            DetailDGVs = ShanuDetailDGV;
            gridColumnIndex = columnIndexs;
            DetailgridDT = DetailTable;
            FilterColumnName = FilterColumn;
           
            MasterDGVs.CellContentClick += new DataGridViewCellEventHandler
                                           (masterDGVs_CellContentClick_Event);
        }
        private void masterDGVs_CellContentClick_Event
                (object sender, DataGridViewCellEventArgs e)
        {           
            DataGridViewImageColumn cols = (DataGridViewImageColumn)MasterDGVs.Columns[0];
         
           // cols.Image = Image.FromFile(ImageName);
            MasterDGVs.Rows[e.RowIndex].Cells[0].Value = Image.FromFile("expand.png");

             if (e.ColumnIndex == gridColumnIndex)
             {            
                 if (ImageName == "expand.png")
                 {
                     DetailDGVs.Visible = true;
                     ImageName = "toggle.png";
                     // cols.Image = Image.FromFile(ImageName);
                     MasterDGVs.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = 
                                                       Image.FromFile(ImageName);

                     String Filterexpression = MasterDGVs.Rows[e.RowIndex].Cells
                                               [FilterColumnName].Value.ToString();

                     MasterDGVs.Controls.Add(DetailDGVs);

                     Rectangle dgvRectangle = MasterDGVs.GetCellDisplayRectangle
                                              (1, e.RowIndex, true);
                     DetailDGVs.Size = new Size(MasterDGVs.Width - 200, 200);
                     DetailDGVs.Location = new Point(dgvRectangle.X, dgvRectangle.Y + 20);

                     DataView detailView = new DataView(DetailgridDT);
                     detailView.RowFilter = FilterColumnName + 
                                            " = '" + Filterexpression + "'";
                     if (detailView.Count <= 0)
                     {
                         MessageBox.Show("No Details Found");
                     }
                     DetailDGVs.DataSource = detailView;
                 }
                 else
                 {
                     ImageName = "expand.png";
                     //  cols.Image = Image.FromFile(ImageName);
                     MasterDGVs.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = 
                                                           Image.FromFile(ImageName);
                     DetailDGVs.Visible = false;
                 }                 
             }
             else
             {
                 DetailDGVs.Visible = false;                 
             }
        }

在单元格点击事件中,如果点击了图片列,我将根据选定的图片名称将图片更改为 Expand(展开)和 Collapse(折叠)。

如果选择图片进行 Expand(展开),那么我将使详情 DataGridView 可见。

在单元格点击事件中,我将获取当前选定的订单号。此订单号将用于“DataView”以仅过滤选定的订单结果。最终结果将绑定到 Detail DataGridView

详情网格设置

在窗体加载时,我调用了此方法在运行时创建 Detail DataGridView

在我的代码中,我在每行之前添加了注释来解释其用途。

        // to generate Detail Datagridview with your coding
        public void DetailGrid_Initialize()
        {
            //First, generate the grid Layout Design
            Helper.ShanuDGVHelper.Layouts(Detail_shanuDGV, Color.Peru, 
            Color.Wheat, Color.Tan, false, Color.Sienna, false, false, false);

            //Set Height, width and add panel to your selected control
            Helper.ShanuDGVHelper.Generategrid
                  (Detail_shanuDGV, pnlShanuGrid, 800, 200, 10, 10);

            // Color Dialog Column creation
            Helper.ShanuDGVHelper.Templatecolumn(Detail_shanuDGV, 
            ShanuControlTypes.BoundColumn, "Order_Detail_No", "Detail No", 
            "Order Detail No", true, 90, DataGridViewTriState.True, 
            DataGridViewContentAlignment.MiddleCenter, 
            DataGridViewContentAlignment.MiddleRight, Color.Transparent, 
            null, "", "", Color.Black);

            // BoundColumn creation
            Helper.ShanuDGVHelper.Templatecolumn
            (Detail_shanuDGV, ShanuControlTypes.BoundColumn, "Order_No", 
            "Order NO", "Order NO", true, 80, DataGridViewTriState.True, 
            DataGridViewContentAlignment.MiddleLeft, 
            DataGridViewContentAlignment.MiddleCenter, Color.Transparent, null, 
            "", "", Color.Black);

            // BoundColumn creation
            Helper.ShanuDGVHelper.Templatecolumn(Detail_shanuDGV, 
            ShanuControlTypes.BoundColumn, "Item_Name", "Item_Name", "Item_Name", 
            true,160, DataGridViewTriState.True, DataGridViewContentAlignment.MiddleLeft, 
            DataGridViewContentAlignment.MiddleCenter, Color.Transparent, null, "", "", 
            Color.Black);

            // BoundColumn creation
            Helper.ShanuDGVHelper.Templatecolumn(Detail_shanuDGV, 
            ShanuControlTypes.BoundColumn, "Notes", "Notes", "Notes", true, 260, 
            DataGridViewTriState.True, DataGridViewContentAlignment.MiddleLeft, 
            DataGridViewContentAlignment.MiddleCenter, Color.Transparent, 
            null, "", "", Color.Black);

            // BoundColumn creation
            Helper.ShanuDGVHelper.Templatecolumn(Detail_shanuDGV, 
            ShanuControlTypes.BoundColumn, "Price", "Price", "Price", true, 70, 
            DataGridViewTriState.True, DataGridViewContentAlignment.MiddleRight, 
            DataGridViewContentAlignment.MiddleCenter, Color.Transparent, null, 
            "", "", Color.Black);

            // BoundColumn creation
            Helper.ShanuDGVHelper.Templatecolumn
            (Detail_shanuDGV, ShanuControlTypes.BoundColumn, "QTY", "QTY", "QTY", 
            true, 40, DataGridViewTriState.True, DataGridViewContentAlignment.MiddleRight, 
            DataGridViewContentAlignment.MiddleCenter, Color.Transparent, null, 
            "", "", Color.Black);
            objshanudgvHelper.DGVDetailGridClickEvents(Detail_shanuDGV);
        }

详情网格单元格点击事件

我调用了上面的方法来为 Detail DataGridView 创建一个单元格点击事件。

 objshanudgvHelper.DGVDetailGridClickEvents(Detail_shanuDGV);

此事件将用于详情网格单元格点击事件。在详情网格的单元格点击时,我将获取每个单元格的文本并显示在 Messagebox 中。

      public void DGVDetailGridClickEvents(DataGridView ShanuDetailDGV)
        {          
            DetailDGVs = ShanuDetailDGV;

            DetailDGVs.CellContentClick += new DataGridViewCellEventHandler
                                           (detailDGVs_CellContentClick_Event);
        }
          private void detailDGVs_CellContentClick_Event(object sender, 
                                             DataGridViewCellEventArgs e)
          {
              MessageBox.Show("Detail grid Clicked : You clicked on " + 
                         DetailDGVs.Rows[e.RowIndex].Cells[e.ColumnIndex].Value);
          }
    }

关注点

此程序解释了创建单级分层 DataGridView 的基本功能。此功能可用于创建多级分层 DataGridView

历史

  • 2014 年 12 月 2 日:版本 1.0
© . All rights reserved.