Introduction
In my previous article, I explained how to create a DatagGridView
helper class using C#.
I extended the DatagGridView
Helper class to create a Nested DatagGridView
. Few days ago, one CodeProject member asked a question on how to create a Nested or Master Detail or Hierarchical DataGridView
for WinForms. I started searching in Google, but didn’t get any result for Nested DataGridView
. I started working on creating a Nested DataGridView
sample program which should be useful to all. As a result, I created a Nested DataGridView
, and you can find the source code from the link at the top of this article. My aim was to create a simple and easy program for users. Users can download the code and customize depending on their requirement.
Why We Need Nested or Hierarchical Datagridview
In real time projects like Order Management, Production Management, etc., we need to display the data in the hierarchical result.
For example, let’s take Order Management project for a restaurant. Let’s consider that four people go to a restaurant to have their lunch. The waiter from the restaurant will give a menu card to select the item to place an order. Now at a Table, a total of four people are sitting. In a restaurant management usually for all tables, there will be a unique Table Id or name. All four people will select their item needed from the menu card 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 Order Detail table. Let’s see an example structure of the order.
Why We Need Master and Detail Table?
To avoid 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, 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 below table for Master and Details.
Order Master Table
Here, we can see the duplicate data has been stored in separate table as a Order Master Table.
Order Detail Table
Here, we can see all the item details of order in a separate table. But in the detail table, we have used the Order NO
for a relation to the Master
table. Using the relation, we can combine both the table and produce the out output.
Normal Grid Result
The result can be shown without using the Hierarchical grid output. But we have to display the duplicate result as below:
We can also merge the same data and show the result like this below table. But the output is not very good and 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. It will be easy to view the master and detail of all records.
Here is my sample output of hierarchical Datagridview
.
Same like Order Management in Restaurant projects, we will have Bill Master and Detail, Account Master and Detail, Item Master and Detail, Inventory Master and Detail. In production projects, we will have Production Order Master and Order Detail, Finished Good Receipt Master and Detail, Finished Goods Issue Master and Detail, etc. Similar to this in all our real time projects, we will use the Master and detail relation to display our data.
Using the Code
As I told you, 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 below functionality to create the nested grid:
ImageCoulmn
DGVMasterGridClickEvents
DGVDetailGridClickEvents
User can use all events like CellClick
, CellContentClick
, etc. for both Master and Detail grid.
I have created two separate list class to populate the master and detail result. In form load, call the method to add the details to each list class.
I have created both 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.
public void MasterGrid_Initialize()
{
Helper.ShanuDGVHelper.Layouts(Master_shanuDGV, Color.LightSteelBlue,
Color.AliceBlue, Color.WhiteSmoke, false, Color.SteelBlue, false, false, false);
Helper.ShanuDGVHelper.Generategrid
(Master_shanuDGV, pnlShanuGrid, 1000, 600, 10, 10);
Helper.ShanuDGVHelper.Templatecolumn(Master_shanuDGV,
ShanuControlTypes.ImageColumn, "img", "", "", true, 26,
DataGridViewTriState.True, DataGridViewContentAlignment.MiddleCenter,
DataGridViewContentAlignment.MiddleRight, Color.Transparent, null,
"", "", Color.Black);
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);
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);
Helper.ShanuDGVHelper.Templatecolumn(Master_shanuDGV,
ShanuControlTypes.BoundColumn, "Description", "Description", "Description",
true, 320, DataGridViewTriState.True, DataGridViewContentAlignment.MiddleLeft,
DataGridViewContentAlignment.MiddleCenter, Color.Transparent, null,
"", "", Color.Black);
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);
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);
DataTable detailTableList = ListtoDataTable
(DataClass.OrderDetailBindClass.objDetailDGVBind);
objshanudgvHelper.DGVMasterGridClickEvents(Master_shanuDGV,
Detail_shanuDGV, Master_shanuDGV.Columns["img"].Index,
ShanuEventTypes.cellContentClick, ShanuControlTypes.ImageColumn,
detailTableList, "Order_No");
Master_shanuDGV.DataSource = DataClass.OrderMasterBindClass.objMasterDGVBind;
}
Cell Click Event
I have called this above method to create a Cell click event for master DataGridView
.
objshanudgvHelper.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 No and filter the result from DataTabledetail
. Display the final Dataview
result to 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];
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";
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";
MasterDGVs.Rows[e.RowIndex].Cells[e.ColumnIndex].Value =
Image.FromFile(ImageName);
DetailDGVs.Visible = false;
}
}
else
{
DetailDGVs.Visible = false;
}
}
In cell click event, if the image column is clicked, 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 visible of the detail DataGridView
.
In cell click event, I will get for the current selected Order No. This Order No 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 Form load, I have called this method to create a Detail DataGridView
at runtime.
In my code, I add the comments before each line to explain its use.
public void DetailGrid_Initialize()
{
Helper.ShanuDGVHelper.Layouts(Detail_shanuDGV, Color.Peru,
Color.Wheat, Color.Tan, false, Color.Sienna, false, false, false);
Helper.ShanuDGVHelper.Generategrid
(Detail_shanuDGV, pnlShanuGrid, 800, 200, 10, 10);
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);
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);
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);
Helper.ShanuDGVHelper.Templatecolumn(Detail_shanuDGV,
ShanuControlTypes.BoundColumn, "Notes", "Notes", "Notes", true, 260,
DataGridViewTriState.True, DataGridViewContentAlignment.MiddleLeft,
DataGridViewContentAlignment.MiddleCenter, Color.Transparent,
null, "", "", Color.Black);
Helper.ShanuDGVHelper.Templatecolumn(Detail_shanuDGV,
ShanuControlTypes.BoundColumn, "Price", "Price", "Price", true, 70,
DataGridViewTriState.True, DataGridViewContentAlignment.MiddleRight,
DataGridViewContentAlignment.MiddleCenter, Color.Transparent, null,
"", "", Color.Black);
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 above method to create a Cell click event for Detail DataGridView
.
objshanudgvHelper.DGVDetailGridClickEvents(Detail_shanuDGV);
This event will be used for the Detail grid Cell Click Event. In cell click of Detail grid, I will get each cell text and display in the 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);
}
}
Points of Interest
This program explains the basic functions to create single level Hierarchical DataGridView
. This same functionality can be used to create multi level Hierarchical DataGridView
.
History
- 2nd December, 2014: Version 1.0