A user in the forums (http://forums.asp.net) is asking how to insert sub rows in GridView and also add delete functionality for the inserted sub rows. In this post I'm going to demonstrate how to this in ASP.NET WebForms. The basic idea to achieve this is we just need to insert row data in the DataSource that is being used in GridView since the GridView rows will be generated based on the DataSource data. To make it more clear then let's build up a sample application. To start fire up Visual Studio and create a WebSite or Web Application project and then add a new WebForm. In the WebForm ASPX page add this GridView markup below: 1: <asp:gridview ID="GridView1" runat="server" AutoGenerateColumns="false" onrowdatabound="GridView1_RowDataBound">
2: <Columns>
3: <asp:BoundField DataField="RowNumber" HeaderText="Row Number" />
4: <asp:TemplateField HeaderText="Header 1">
5: <ItemTemplate>
6: <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
7: </ItemTemplate>
8: </asp:TemplateField>
9: <asp:TemplateField HeaderText="Header 2">
10: <ItemTemplate>
11: <asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
12: </ItemTemplate>
13: </asp:TemplateField>
14: <asp:TemplateField HeaderText="Header 3">
15: <ItemTemplate>
16: <asp:TextBox ID="TextBox3" runat="server"></asp:TextBox>
17: </ItemTemplate>
18: </asp:TemplateField>
19: <asp:TemplateField HeaderText="Action">
20: <ItemTemplate>
21: <asp:LinkButton ID="LinkButton1" runat="server" onclick="LinkButton1_Click" Text="Insert"></asp:LinkButton>
22: </ItemTemplate>
23: </asp:TemplateField>
24: </Columns>
25: </asp:gridview>
Then at the code behind source of ASPX page you can add this codes below:
1: private DataTable FillData() {
2:
3: DataTable dt = new DataTable();
4: DataRow dr = null;
5:
6: //Create DataTable columns
7: dt.Columns.Add(new DataColumn("RowNumber", typeof(string)));
8:
9: //Create Row for each columns
10: dr = dt.NewRow();
11: dr["RowNumber"] = 1;
12: dt.Rows.Add(dr);
13:
14: dr = dt.NewRow();
15: dr["RowNumber"] = 2;
16: dt.Rows.Add(dr);
17:
18: dr = dt.NewRow();
19: dr["RowNumber"] = 3;
20: dt.Rows.Add(dr);
21:
22: dr = dt.NewRow();
23: dr["RowNumber"] = 4;
24: dt.Rows.Add(dr);
25:
26: dr = dt.NewRow();
27: dr["RowNumber"] = 5;
28: dt.Rows.Add(dr);
29:
30: //Store the DataTable in ViewState for future reference
31: ViewState["CurrentTable"] = dt;
32:
33: return dt;
34:
35: }
36:
37: private void BindGridView(DataTable dtSource) {
38: GridView1.DataSource = dtSource;
39: GridView1.DataBind();
40: }
41:
42: private DataRow InsertRow(DataTable dtSource, string value) {
43: DataRow dr = dtSource.NewRow();
44: dr["RowNumber"] = value;
45: return dr;
46: }
47: //private DataRow DeleteRow(DataTable dtSource,
48:
49: protected void Page_Load(object sender, EventArgs e) {
50: if (!IsPostBack) {
51: BindGridView(FillData());
52: }
53: }
54:
55: protected void LinkButton1_Click(object sender, EventArgs e) {
56: LinkButton lb = (LinkButton)sender;
57: GridViewRow row = (GridViewRow)lb.NamingContainer;
58: DataTable dtCurrentData = (DataTable)ViewState["CurrentTable"];
59: if (lb.Text == "Insert") {
60: //Insert new row below the selected row
61: dtCurrentData.Rows.InsertAt(InsertRow(dtCurrentData, row.Cells[0].Text + "-sub"), row.RowIndex + 1);
62:
63: }
64: else {
65: //Delete selected sub row
66: dtCurrentData.Rows.RemoveAt(row.RowIndex);
67: }
68:
69: BindGridView(dtCurrentData);
70: ViewState["CurrentTable"] = dtCurrentData;
71: }
72:
73: protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e) {
74: if (e.Row.RowType == DataControlRowType.DataRow) {
75: if (e.Row.Cells[0].Text.Contains("-sub")) {
76: ((LinkButton)e.Row.FindControl("LinkButton1")).Text = "Delete";
77: }
78: }
79: }
As you can see the code above is pretty straight forward and self explainatory but just to give you a short explaination the code above is composed of three (3) private methods which are the FillData(), BindGridView and InsertRow(). The FillData() method is a method that returns a DataTable and basically creates a dummy data in the DataTable to be used as the GridView DataSource. You can replace the code in that method if you want to use actual data from database but for the purpose of this example I just fill the DataTable with a dummy data on it. The BindGridVew is a method that handles the actual binding of GridVew. The InsertRow() is a method that returns a DataRow. This method handles the insertion of the sub row.
Now in the LinkButton OnClick event, we casted the sender to a LinkButton to determine the specific object that fires up the event and get the row values. We then reference the Data from ViewState to get the current data that is being used in the GridView. If the LinkButton text is "Insert" then we will insert new row to the DataSource ( in this case the DataTable) based on the rowIndex if not then Delete the sub row that was added.
Here are some screen shots of the output below:
On initial load:
After inserting a sub row:
That's it! I hope someone find this post useful!
Technorati Tags: ASP.NET,C#,GridView