Share via


Master Detail DataGridView C# Winform

You can download the complete Source code from this link Master Detail DataGridView C# Winform Introduction

https://code.msdn.microsoft.com/site/view/file/140926/1/2.JPG

*In my previous article I explained how to Create a DatagGridView helper class using C# 
I have extended the DatagGridView Helper class to create a Master/Detail DatagGridView. My intent is to create a simple and easy program for users. Users can download the code and can customize it depending on their requirements.

Why to use a Nested or Hierarchical DataGridView
In real projects like Order Management, Production Management and and so on we need to display the data in the hierarchical result.
For example let's use an Order Management project for a restaurant. Let's consider four people going to a restaurant to have their lunch. The waiter from the restaurant will provide a menu card to select the item to place an order. Now in a table the total of 4 people are sitting in a restaurant. In restaurant management, usually all the tables have a unique Table Id or name. All 4 people will select their item from the menu and place the order to serve their food. In restaurant management for each order we will create a unique id in an Order Master table and all the item details related to the order in the Order Detail table. Let's see an example structure of the order.

Why to use a Master and Detail Table 
To avoid the duplicate data we can use the master Detail table relation to store our data. For example for every order there will be one waiter and one Table so if we didn't use the Master Detail table relation then the output will be like this below.*

https://code.msdn.microsoft.com/site/view/file/140927/1/t1.JPG

Here we can see that Order No, Table ID, Waiter Name and Order Date have been repeated. To avoid this duplicate data we will create a Master and Detail relation tables. See the following table for Master and Details.
Order Master Table
Here we can see that the duplicate data has been stored in a separate table as an Order Master Table.

https://code.msdn.microsoft.com/site/view/file/140928/1/t2.JPG

Order Detail Table
Here we can see all the item details of the order in a separate table. But in the detail table we have used the Order Number for a relation to the Master table. Using the relation we can combine both tables and produce the output.

https://code.msdn.microsoft.com/site/view/file/140929/1/t3.JPG

Normal grid result
The result can be shown without using the Hierarchal grid output. But we must display the duplicate results as in the following.

https://code.msdn.microsoft.com/site/view/file/140930/1/t4.JPG

We can also merge the same data and show the result as in the following table. But the output is not much better and is not easy to view and understand.

https://code.msdn.microsoft.com/site/view/file/140931/1/t5.JPG

*Let's see now the hierarchical output of the same result. * 

https://code.msdn.microsoft.com/site/view/file/140932/1/t6.JPG

Now this final result looks much better than all the previous. It will be easy to view the master and detail of all records. Here is my sample output of the hierarchical DataGridView.

 https://code.msdn.microsoft.com/site/view/file/140933/1/3.JPG

In the same manner as Order Management in restaurant projects we also have Bill Master and Detail, Account Master and Detail, Item Master and Detail and Inventory Master and Detail. In production projects we will have Production Order Master and Oder Detail, Finished Good Receipt Master and Detail, Finished Goods Issue Master and Detail and so on. In the same manner in our all our actual projects we will use the Master and detail relation to display our data.

Building the Sample

As I explained in this article, I have used and extended my DataGridView helper class to create a Nested DataGridView. You can view my DataGridView helper class details from my article.

In my DGVhelper class I have added the following functionality to create the nested grid.

  • ImageCoulmn 
  • DGVMasterGridClickEvents 
  • DGVDetailGridClickEvents 

The user can use all the events, like CellClick, CellContentClick and and so on for both the Master and Detail grid.

I have created two separate list classes to populate the master and detail results. In the form load I called the method to add the details to each list class.
I have created both a Master and Detail DataGridView programmatically (dynamically) using my ShanuDGVHelper Class. 

Description

*Master Grid Setting: In Form Load I have called this method to create a master DataGridView at runtime. In my code I add the comments before each line to explain its use.
*

/ 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 Colum 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; 
        }

Cell Click Event: I have called this the preceding method to create a Cell click event for the master DataGridView.

*

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

 This event will be used for the master grid image click event. In this event I will get the Order Number and filter the result from DataTabledetail. Display the final Dataview result to the detail DataGridView. 

// Image Colukmn Click evnet 
        #region Image Colukmn Click Event 
        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;                 
             } 
        } 
        #endregion

In the cell click event if the image column is clicked then I will change the image to Expand and Collapse depending on the selected image name. If the image is selected to Expand then I will make the detail DataGridView visible.
In the cell click event I will get something for the current selected Order Number. This order number will be used in “DataView” to filter only the selected order result. The final result will be bound to the detail DataGridView.
Detail Grid Setting: In the Form load I have called this method to create a detail DataGridView at runtime.
In my code I added comments before each line to explain its use.

// 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 Grid Cell Click Event: I have called this the preceding method to create a Cell click event for the detail DataGridView.

objshanudgvHelper.DGVDetailGridClickEvents(Detail_shanuDGV);

This event will be used for the detail grid Cell Click event. In the cell click of the Detail grid I will get each cell text and display it in a 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); 
          }

https://code.msdn.microsoft.com/site/view/file/140934/1/4.JPG

 Source Code Files

You can download the complete Source code from this link Master Detail DataGridView C# Winform