2
\$\begingroup\$

I need to add a list of names and (optional) links to my ASP.net page.

I learnt (hopefully) to use a GridView to do this, mostly working from the example given by this blog entry: adding-dynamic-rows-in-gridview.

I've added a GridView to my frontend:

<asp:GridView
 id="NameLinksGridView" runat="server"
 AutoGenerateColumns="false" ShowFooter="true">
 <Columns>
 <asp:TemplateField HeaderText="Name">
 <ItemTemplate>
 <asp:TextBox ID="Name" runat="server" />
 </ItemTemplate>
 </asp:TemplateField> 
 <asp:TemplateField HeaderText="Link">
 <ItemTemplate>
 <asp:TextBox ID="Link" runat="server" />
 </ItemTemplate>
 <FooterStyle HorizontalAlign="Right" />
 <FooterTemplate>
 <asp:Button 
 ID="addNameLink" runat="server"
 Text="Add" onclick="addNameLink_Click"
 CausesValidation="false" />
 </FooterTemplate> 
 </asp:TemplateField>
 </Columns>
</asp:GridView>

With the code behind:

private void setupInitialNameLinks()
{
 DataTable dt = getNameLinksTable();
 /* store DataTable in the ViewState for preservation across PostBack's */
 ViewState["CurrentTable"] = dt;
 /* bind the displayed DataGrid to our DataTable */
 NameLinksGridView.DataSource = dt;
 NameLinksGridView.DataBind();
 /* set current TextBox values to the values in the DataTable 
 * surely the DataBind should do this for us?!? */
 setTextBoxValuesToDataTableValues(dt);
}
private DataTable getNameLinksTable()
{
 DataTable dt = new DataTable();
 dt.Columns.Add(new DataColumn("Name", typeof(string)));
 dt.Columns.Add(new DataColumn("Link", typeof(string)));
 var existingNameLinks = getExistingNameLinks();
 if (existingNameLinks.Count() > 0)
 {
 foreach (var auth in existing)
 {
 DataRow r = dt.NewRow();
 r["Name"] = auth.name;
 r["Link"] = auth.link;
 dt.Rows.Add(r);
 }
 }
 else
 {
 DataRow emptyRow = getNameLinksEmptyRow(dt);
 dt.Rows.Add(emptyRow);
 }
 return dt;
}
private static DataRow getNameLinksEmptyRow(DataTable dt)
{
 DataRow emptyRow = dt.NewRow();
 emptyRow["Name"] = String.Empty;
 emptyRow["Link"] = String.Empty;
 return emptyRow;
}
protected void addNameLink_Click(object sender, EventArgs e)
{
 if (ViewState["CurrentTable"] != null)
 {
 DataTable dt = (DataTable) ViewState["CurrentTable"];
 DataRow dr = getNameLinksEmptyRow(dt);
 dt.Rows.Add(dr);
 /* update our DataTable to the POST'ed data */
 int numPostedRows = dt.Rows.Count - 1;
 for (int i = 0; i < numPostedRows; i++)
 {
 TextBox tbName = 
 (TextBox)NameLinksGridView.Rows[i].Cells[0].FindControl("Name");
 string name = tbName.Text; // get POST'ed value
 dt.Rows[i]["Name"] = name; // set DataTable val to the POST'ed value
 TextBox tbLink = 
 (TextBox)NameLinksGridView.Rows[i].Cells[1].FindControl("Link");
 string link = tbLink.Text;
 dt.Rows[i]["Link"] = link;
 }
 /* store our DataTable in the ViewState for preservation across PostBack */
 ViewState["CurrentTable"] = dt;
 /* bind the displayed DataGrid to our DataTable */
 NameLinksGridView.DataSource = dt;
 NameLinksGridView.DataBind();
 /* set current TextBox values to the values in the DataTable
 * needs to happen after the DataBind()
 * surely the DataBind should do this for us?!? */
 setTextBoxValuesToDataTableValues(dt);
 }
 else
 {
 throw new Exception("CurrentTable is null!");
 }
}
private void setTextBoxValuesToDataTableValues(DataTable dt)
{
 for (int i = 0; i < dt.Rows.Count; i++)
 {
 TextBox tbName = (TextBox)NameLinksGridView.Rows[i].Cells[0].FindControl("Name");
 tbName.Text = dt.Rows[i]["Name"].ToString();
 TextBox tbLink = (TextBox)NameLinksGridView.Rows[i].Cells[1].FindControl("Link");
 tbLink.Text = dt.Rows[i]["Link"].ToString();
 }
}

Does any of this code look troublesome, prone to error, umnaintanable, not the right way of doing it, etc?

One big bit of confusion I have (even though the code works) — why do I need to store the DataTable in the ViewState manually and set my TextBox displayed values manually (in setTextBoxValuesToDataTableValues)? Surely the GridView state should be maintained across the POST without me needing to worry about the ViewState and the DataBind should set the TextBox values automatically?

Glorfindel
1,1133 gold badges14 silver badges27 bronze badges
asked Dec 11, 2011 at 11:35
\$\endgroup\$
1
  • \$\begingroup\$ The KetticGridView is capable of populating gridview with data using DataTable to a single data table or dataset, as well as to multiple data tables through hierarchical data binding. \$\endgroup\$ Commented Feb 8, 2014 at 9:38

1 Answer 1

2
\$\begingroup\$

Regarding having to get/set the value of the textboxes, you should get to know the Bind expression. For instance, you could have:

<asp:TextBox ID="Name" runat="server" Text='<%# Bind("Name") %>' /> 

For one of the "right" ways of doing things, have a look at this walkthrough of bulk editing rows in the GridView control.

Steven Jeuris
2,6623 gold badges21 silver badges34 bronze badges
answered Dec 13, 2011 at 12:37
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.