Introduction
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.
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.![]()
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.
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.
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.
Let's see now the hierarchical output of the same result.
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.
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.
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
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.
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;
- }
- // 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");
- // 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 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);
- }
- objshanudgvHelper.DGVDetailGridClickEvents(Detail_shanuDGV);
- 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);
- }


Md. KarimPosted Dec 27, 2018, 9:38 PM
How to load data from sql database?
Mayeen ChowdhuryPosted Jan 4, 2017, 5:09 PM
I'm too late to get you, Very nice and helpful article.
Syed ShanuPosted Apr 3, 2015, 3:40 AM
Iam glad you like my articles thank you Altaf
Altaf AnsariPosted Apr 3, 2015, 3:39 AM
i saw your previous Winform Examples, the way you code is interesting...
Syed ShanuPosted Apr 3, 2015, 3:39 AM
Thank You Altaf
Altaf AnsariPosted Apr 3, 2015, 3:37 AM
What a great piece of coding...
Syed ShanuPosted Apr 1, 2015, 11:14 PM
Thank You Afzaal :)
Afzaal Ahmad ZeeshanPosted Apr 1, 2015, 11:06 PM
Great article Shanu. :)
Syed ShanuPosted Apr 1, 2015, 6:01 PM
Thanks Uday Kumar
Syed ShanuPosted Apr 1, 2015, 6:01 PM
Thanks Nitin
Udaya kumarPosted Apr 1, 2015, 4:19 PM
Good article
NitinPosted Apr 1, 2015, 9:23 AM
great work
Syed ShanuPosted Mar 31, 2015, 9:26 AM
Thank You
Tom MohanPosted Mar 31, 2015, 9:13 AM
good effort
Syed ShanuPosted Mar 31, 2015, 1:34 AM
Thank You Khargesh
Khargesh RajputPosted Mar 31, 2015, 1:31 AM
nice sir
Syed ShanuPosted Mar 31, 2015, 1:16 AM
Thank You Saber
Saber ShaikhPosted Mar 31, 2015, 12:53 AM
Great article
Syed ShanuPosted Mar 30, 2015, 10:25 PM
Thank You Gowtham
Gowtham RajamanickamPosted Mar 30, 2015, 10:10 PM
great...
Syed ShanuPosted Mar 30, 2015, 4:43 PM
Thsnk you
Del WoodcockPosted Mar 30, 2015, 2:09 PM
Great article!