Add new row(s) to GridView

转载自 大熊爱黄毛


I’ve got some questions about how to add a new row to the GridView programmatically, for example when a row is selected we maybe want to add a DetailsView beneath the selected row for displaying more information about the row.

 

Let’s see how we can add a new row dynamically to the GridView control. There are some properties and event’s that we can’t use, for example, the Rows property of the GridView is protected from adding new rows, so we can’t use the Rows property to add a new row programmatically. The RowCreated event will only provide us with the current row created, but we can’t add a new row in the RowCreated event either to the GridView. It would be possible if Microsoft has made the internal table available from the Parent property of the created row, but they don’t set the Parent to an object. That will be done after the RowCreated event has been executed. But the RowDataBound event will be trigged directly after the Row has been added to the internal table. With the RowDataBound event we can get the table where the Row is added through the Row’s Parent property:

 

void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)

{

     ChildTable table = e.Row.Parent as ChildTable;

     if (table != null)

        //Add new row ro the table

}

 

Now when we can get the table that we can dynamically add our own row to the table:

 

void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)

{

    if (e.Row.RowType == DataControlRowType.DataRow)

    {

        ChildTable table = e.Row.Parent as ChildTable;

 

        if (table != null)

        {

           GridViewRow row = new GridViewRow(-1, -1, DataControlRowType.DataRow, DataControlRowState.Normal);


           TableCell cell = new TableCell();

           cell.ColumnSpan = GridView1.Columns.Count;

           cell.Width = Unit.Percentage(100);

 

           cell.Controls.Add(new LiteralControl("New Row"));

 

           row.Cells.Add(cell);

 

           table.Rows.Add(row);

        }

    }

}

 

The code above will add a new GridViewRow to the GridView. The new row will have one cell that has the width of the GridView. To make this code more readable we can do some refactoring:

 

void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)

{

     if (e.Row.RowType == DataControlRowType.DataRow)

     {

         ChildTable table = e.Row.Parent as ChildTable;

 

         if (table != null)

            CreateRow(table);

     }

}

 

private void CreateRow(ChildTable table)

{

     GridViewRow row = new GridViewRow(-1, -1, DataControlRowType.DataRow, DataControlRowState.Normal);

     row.Cells.Add(CreateColumn());

     table.Rows.Add(row);

}

 

private TableCell CreateColumn()

{

     TableCell cell = new TableCell();

     cell.ColumnSpan = GridView1.Columns.Count;

     cell.Width = Unit.Percentage(100);

 

     cell.Controls.Add(new LiteralControl("New Row"));

   

     return cell;

}

 

There are now two methods, one that creates the row and one that creates our column.

 

Because the RowDataBound will only be executed the first time the GridView is rendered, we have to turn of the ViewState for the GridView to make it execute the RowDataBound event every time the page is requested.

 

Note: This could remove some functionality so have that in mind.

 

If we runt the code above, we will add a new row for each row to the GridView control.

Instead of adding a new row for each row, we can instead add a new row only when a row is selected. By doing this we use the GridView’s DataBound event and the GridView’s SelectedRow property to get the Row and the Row’s parent control:

 

void GridView1_DataBound(object sender, EventArgs e)

{

     if (GridView1.SelectedRow != null)

     {

         ChildTable table = GridView1.SelectedRow.Parent as ChildTable;

 

         if (table != null)

            CreateRow(table, GridView1.SelectedIndex);

     }

}

 

The code above calls the CreateRow method to create the new row. The CreateRow method has a new argument with the value of selected row’s index. The reason why we have to pass the index of the selected row is that we have to know where to add the new row to the GridView control. If we use the Add method of the table where the row belongs to, the row will be added at the end of the GridView control. The following code is the new CreateRow method:

 

private void CreateRow(ChildTable table, int index)

{

     GridViewRow row = new GridViewRow(-1, -1, DataControlRowType.DataRow, DataControlRowState.Normal);

     row.Cells.Add(CreateColumn());

     table.Rows.AddAt(index+2, row);

}

 

In the code above the AddAt method is used to add the new row. We have to increase the GirdView’s SelctedIndex by two, for making the row appear under our selected row. If we don’t increase the index, the row will be added above the selected row or on the same position that will also make the created row appear before the selected row. If we run the new code and select a row from the GridView, our created row will be displayed under the selected row.

 

Now when we have added a row for the selected row we can simply add a DetailsView control that will display detailed information about the selected row. The following code will create a SqlDataSource control and a DetalsView control dynamically:

 

private TableCell CreateColumn()

{

     TableCell cell = new TableCell();

     cell.ColumnSpan = GridView1.Columns.Count;

     cell.Width = Unit.Percentage(100);

 

     SqlDataSource ds = new SqlDataSource();

     ds.ConnectionString = ConfigurationSettings.ConnectionStrings["AppConnectionString1"].ConnectionString;

     ds.SelectCommand = "SELECT * FROM [Customers] WHERE [CustomerID] = @CustomerID";

     ds.ID = "SqlDataSource2";

 

     Parameter cp = new Parameter("CustomerID", TypeCode.String, GridView1.SelectedValue.ToString());

     ds.SelectParameters.Add(cp);

 

     DetailsView dv = new DetailsView();

     dv.AutoGenerateRows = true;

     dv.DataSourceID = "SqlDataSource2";

 

     cell.Controls.Add(ds);

     cell.Controls.Add(dv);

   

     return cell;

}

 

In the code above, we have only changed the CreateColumn method to create a DetailsView and the SqlDataSource control. We could also do some refactoring to make the code more readable and maintainable:

 

private TableCell CreateColumn()

{

     TableCell cell = new TableCell();

     cell.ColumnSpan = GridView1.Columns.Count;

     cell.Width = Unit.Percentage(100);

 

     DataSourceControl ds = CreateDataSourceControl();

 

     cell.Controls.Add(ds);

     cell.Controls.Add(CreateDetailsView(ds));

 

     return cell;

}

   

private static DetailsView CreateDetailsView(DataSourceControl ds)

{

     DetailsView dv = new DetailsView();

     dv.AutoGenerateRows = true;

     dv.DataSourceID = ds.ID;

     return dv;

}

 

private DataSourceControl CreateDataSourceControl()

{

     SqlDataSource ds = new SqlDataSource();

     ds.ConnectionString = ConfigurationSettings.ConnectionStrings["AppConnectionString1"].ConnectionString;

     ds.SelectCommand = "SELECT * FROM [Customers] WHERE [CustomerID] = @CustomerID";

     ds.ID = "SqlDataSource2";

 

     Parameter cp = new Parameter("CustomerID", TypeCode.String, GridView1.SelectedValue.ToString());

     ds.SelectParameters.Add(cp);

     return ds;

}

 

There are now two more method, one that creates the DataSourceControl and one that creates the DetailsView control. The CreateDatSourceControl method will return the base class of the SqlDataSourceControl, this will make it easy for us to simply change the code inside the CreateDataSourceControl to return another data source control with a little of work.

 

Here is the final code for displaying a DetailsView control when a row from the GridView is selected:

 

<%@ Page Language="C#" %>

 

<script runat="server">

 

    void GridView1_DataBound(object sender, EventArgs e)

    {

        if (GridView1.SelectedRow != null)

        {

            ChildTable table = GridView1.SelectedRow.Parent as ChildTable;

 

            if (table != null)

                CreateRow(table, GridView1.SelectedIndex);

        }

    }

 

    private void CreateRow(ChildTable table, int index)

    {

        GridViewRow row = new GridViewRow(-1, -1, DataControlRowType.DataRow, DataControlRowState.Normal);

        row.Cells.Add(CreateColumn());

        table.Rows.AddAt(index + 2, row);

    }

 

    private TableCell CreateColumn()

    {

        TableCell cell = new TableCell();

        cell.ColumnSpan = GridView1.Columns.Count;

        cell.Width = Unit.Percentage(100);

 

        DataSourceControl ds = CreateDataSourceControl();

 

        cell.Controls.Add(ds);

        cell.Controls.Add(CreateDetailsView(ds));

 

        return cell;

    }

 

    private static DetailsView CreateDetailsView(DataSourceControl ds)

    {

        DetailsView dv = new DetailsView();

        dv.AutoGenerateRows = true;

        dv.DataSourceID = ds.ID;

        return dv;

    }

 

    private DataSourceControl CreateDataSourceControl()

    {

        SqlDataSource ds = new SqlDataSource();

        ds.ConnectionString = ConfigurationSettings.ConnectionStrings["AppConnectionString1"].ConnectionString;

        ds.SelectCommand = "SELECT * FROM [Customers] WHERE [CustomerID] = @CustomerID";

        ds.ID = "SqlDataSource2";

 

        Parameter cp = new Parameter("CustomerID", TypeCode.String, GridView1.SelectedValue.ToString());

        ds.SelectParameters.Add(cp);

        return ds;

    }   

   

</script>

 

<html xmlns="http://www.w3.org/1999/xhtml" >

<head runat="server">

    <title>Untitled Page</title>

</head>

<body>

    <form id="form1" runat="server">

    <div>

        &nbsp;<asp:GridView ID="GridView1" Runat="server" DataSourceID="SqlDataSource1" DataKeyNames="CustomerID"

            AutoGenerateColumns="False" OnDataBound="GridView1_DataBound" EnableViewState="False">

            <Columns>

                <asp:CommandField ShowSelectButton="True"></asp:CommandField>

                <asp:BoundField ReadOnly="True" HeaderText="CustomerID" DataField="CustomerID" SortExpression="CustomerID"></asp:BoundField>

                <asp:BoundField HeaderText="ContactName" DataField="ContactName" SortExpression="ContactName"></asp:BoundField>

            </Columns>

        </asp:GridView>

        <asp:SqlDataSource ID="SqlDataSource1" Runat="server" SelectCommand="SELECT [CustomerID], [ContactName] FROM [Customers]"

            ConnectionString="<%$ ConnectionStrings:AppConnectionString1 %>">

        </asp:SqlDataSource>

    </div>

    </form>

</body>

</html>

 

If you have any questions about this post, please drop me an e-mail and I will try to answer them. Lately I got several e-mails with questions and I have not the time to answer all of them but I will try to do my best.

转载于:https://www.cnblogs.com/jerryhong/articles/706927.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值