DataGrid - Adding Rows

J

Jim Heavey

Trying to figure out the technique which should be used
to add rows to a datagrid. I am thinking that I would
want an "Add" button on the footer, but I am not quite
sure how to do that. Is that the best method? Do you
have a sample of how to do this?
 
M

Mike Moore [MSFT]

Hi Jim,

There's an article that addresses this subject.

Top Questions about the DataGrid Web Server Control
http://msdn.microsoft.com/library/en-us/dv_vstechart/html/vbtchTopQuestionsA
boutASPNETDataGridServerControl.asp

Here is the relevant section.

Adding Columns Dynamically
You can hide and show columns if you know in advance what columns you need.
Sometimes, however, you do not know that until run time. In that case, you
can create columns dynamically and add them to the grid.

To do so, you create an instance of one of the column classes supported by
the grid — BoundColumn, EditCommandColumn, ButtonColumn, or
HyperlinkColumn. (You can add template columns to the grid, but it is
slightly more complex. For details, see Creating Web Server Control
Templates Programmatically.) Set the column's properties, and then add it
to the grid's Columns collection.

The following example shows how to add two bound columns to a grid.

' Visual Basic
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
'Set data-binding properties of the grid
DataGrid1.AutoGenerateColumns = False
DataGrid1.DataSource = Me.dsBooks1
DataGrid1.DataMember = "Books"
DataGrid1.DataKeyField = "bookid"

' Add two columns
Dim dgc_id As New BoundColumn()
dgc_id.DataField = "bookid"
dgc_id.HeaderText = "ID"
dgc_id.ItemStyle.Width = New Unit(80)
DataGrid1.Columns.Add(dgc_id)

Dim dgc_title As New BoundColumn()
dgc_title.DataField = "title"
dgc_title.HeaderText = "Title"
DataGrid1.Columns.Add(dgc_title)

Me.SqlDataAdapter1.Fill(Me.dsBooks1)
DataGrid1.DataBind()
End Sub

// C#
private void Button1_Click(object sender, System.EventArgs e)
{
DataGrid1.AutoGenerateColumns = false;
DataGrid1.DataSource = this.dsBooks1;
DataGrid1.DataMember = "Books";
DataGrid1.DataKeyField = "bookid";

// Add two columns
BoundColumn dgc_id = new BoundColumn();
dgc_id.DataField = "bookid";
dgc_id.HeaderText = "ID";
dgc_id.ItemStyle.Width = new Unit(80);
DataGrid1.Columns.Add(dgc_id);

BoundColumn dgc_title= new BoundColumn();
dgc_title.DataField = "title";
dgc_title.HeaderText = "Title";
DataGrid1.Columns.Add(dgc_title);

this.sqlDataAdapter1.Fill(this.dsBooks1);
DataGrid1.DataBind();
}
Any time that you add controls to a page dynamically, you have the problem
of persistence. Dynamically-added controls (or in this case, columns) are
not automatically added to the page's view state, so you are obliged to add
logic to the page to make sure the columns are available with each round
trip.

An excellent way to do this is to override the page's LoadViewState method,
which gives you an early opportunity to reestablish columns in the DataGrid
control. Because the LoadViewState method is called before the Page_Load
event is raised, re-adding columns in the LoadViewState method assures that
they are available for normal manipulation by the time any event code runs.

The following example shows how you would expand the previous example to
restore the columns each time the page runs again. As before, the
Button1_Click handler adds two columns to the grid. (In this example, the
event handler calls a separate routine called AddColumns to do so.) In
addition, the page contains a simple Boolean property called
DynamicColumnsAdded indicating whether the grid has had columns added; the
property persists its value in view state. The LoadViewState method first
calls the base class's LoadViewState method, which extracts view state
information and configures controls with it. If columns were previously
added to the grid (as per the DynamicColumnsAdded property), the method
then re-adds them.

' Visual Basic
Private Property DynamicColumnAdded() As Boolean
Get
If ViewState("ColumnAdded") Is Nothing Then
Return False
Else
Return True
End If
End Get
Set(ByVal Value As Boolean)
ViewState("ColumnAdded") = Value
End Set
End Property

Protected Overrides Sub LoadViewState(ByVal savedState As Object)
MyBase.LoadViewState(savedState)
If Me.DynamicColumnAdded Then
Me.AddColums()
End If
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
' Check property to be sure columns are not added more than once
If Me.DynamicColumnAdded Then
Return
Else
Me.AddColums()
End If
End Sub

Protected Sub AddColums()
' Add two columns
Dim dgc_id As New BoundColumn()
dgc_id.DataField = "instock"
dgc_id.HeaderText = "In Stock?"
dgc_id.ItemStyle.Width = New Unit(80)
DataGrid1.Columns.Add(dgc_id)

Dim dgc_title As New BoundColumn()
dgc_title.DataField = "title"
dgc_title.HeaderText = "Title"
DataGrid1.Columns.Add(dgc_title)
Me.DataGrid1.DataBind()
Me.DynamicColumnAdded = True
End Sub

// C#
private bool DynamicColumnAdded{
get
{
object b = ViewState["DynamicColumnAdded"];
return (b == null) ? false : true;
}
set
{
ViewState["DynamicColumnAdded"] = value;
}
}

protected override void LoadViewState(object savedState)
{
base.LoadViewState(savedState);
if (DynamicColumnAdded)
{
this.AddColumns();
}
}

private void Button1_Click(object sender, System.EventArgs e)
{
if(this.DynamicColumnAdded != true)
{
this.AddColumns();
}
}

private void AddColumns()
{
BoundColumn dgc_id = new BoundColumn();
dgc_id.DataField = "bookid";
dgc_id.HeaderText = "ID";
dgc_id.ItemStyle.Width = new Unit(80);
DataGrid1.Columns.Add(dgc_id);

BoundColumn dgc_title= new BoundColumn();
dgc_title.DataField = "title";
dgc_title.HeaderText = "Title";
DataGrid1.Columns.Add(dgc_title);

this.sqlDataAdapter1.Fill(this.dsBooks1);
DataGrid1.DataBind();
this.DynamicColumnAdded = true;
}
Adding New Records to a Data Source Using the DataGrid Control
The DataGrid control allows users to view and edit records, but does not
inherently include the facility to add new ones. However, you can add this
functionality in various ways, all of which involve the following:

Adding a new, blank record to the data source of the grid (in the dataset
or database). If necessary, you will need to assign an ID for the record
and put placeholder values into it for any columns that cannot be null.
Rebinding the DataGrid control to the source.
Putting the grid into edit mode for the new record. You need to be able to
determine where in the grid the new record appears.
Updating the record normally when the user clicks Update, thereby writing
the new record to the source with user-provided values.
The following example shows the process for adding the new record, binding
the grid, and putting it into edit mode. In this example, the data source
is a dataset (DsBooks1 or dsBooks1) containing a table called "Books."

' Visual Basic
Private Sub btnAddRow_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnAddRow.Click
Dim dr As DataRow = Me.DsBooks1.Books.NewRow
dr("title") = "(New)"
dr("instock") = True
Me.DsBooks1.Books.Rows.InsertAt(dr, 0)
Session("DsBooks") = DsBooks1
DataGrid1.EditItemIndex = 0
DataGrid1.DataBind()
End Sub

// C#
private void btnAddRow_Click(object sender, System.EventArgs e)
{
DataRow dr = this.dsBooks1.Books.NewRow();
dr["title"] = "(New)";
dr["instock"] = true;
this.dsBooks1.Books.Rows.InsertAt(dr, 0);
Session["DsBooks"] = dsBooks1;
DataGrid1.EditItemIndex = 0;
DataGrid1.DataBind();
}
Some things to notice:

This code runs when a user clicks an Add button somewhere in the page.
The new row is created using the NewRow method. It is then inserted into
the dataset table using the InsertAt method, which allows you to place it
at a specific, predefined location — in this case, as the first record in
the table (that is, the first record in the Rows collection).
Alternatively, you could add it to the end of the table, using the row
count as the value. The important thing is that you know exactly where the
row is in the table.
Because you know that the record is in the first position of the table, you
can set the grid's EditItemIndex value to zero to put the new row into edit
mode. (If you created the row elsewhere in the table, you would set
EditItemIndex to that location instead.)
Because you have a new record in the dataset (but not yet in the database),
you have to keep a copy of the dataset between round trips — you do not
want to refill it from the database and lose the new record. Here, the code
stores it in Session state. You need to reload the dataset from Session
state when the page loads. The following example shows what your Page_Load
handler might look like:
' Visual Basic
Private Sub Page_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
If Me.IsPostBack Then
DsBooks1 = CType(Session("DsBooks"), dsBooks)
Else
Me.SqlDataAdapter1.Fill(Me.DsBooks1)
Session("DsBooks") = DsBooks1
DataGrid1.DataBind()
End If
End Sub

// C#
private void Page_Load(object sender, System.EventArgs e)
{
if(this.IsPostBack)
{
dsBooks1 = (dsBooks) Session["DsBooks"];
}
else
{
this.sqlDataAdapter1.Fill(this.dsBooks1);
Session["DsBooks"] = dsBooks1;
this.DataGrid1.DataBind();
}
}
For information about maintaining state, see Web Forms State Management in
the Visual Studio documentation.

You can update the record normally. For an example, see Walkthrough: Using
a DataGrid Web Control to Read and Write Data in the Visual Studio
documentation. After updating the dataset, update the database, then
refresh the dataset. Be sure to save the refreshed dataset to Session state
again. Here is an example of an update handler:

' Visual Basic
Private Sub DataGrid1_UpdateCommand(ByVal source As Object, _
ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) _
Handles DataGrid1.UpdateCommand
Dim dr As Dataset.BooksRow
'Get a reference to row zero (where the row was inserted)
dr = Me.DsBooks1.Books(0)
Dim tb As TextBox = CType(e.Item.Cells(2).Controls(0), TextBox)
dr.title = tb.Text
Dim cb As CheckBox = CType(e.Item.Cells(3).Controls(1), CheckBox)
dr.instock = cb.Checked
Me.SqlDataAdapter1.Update(Me.DsBooks1)
DataGrid1.EditItemIndex = -1
'Refresh the dataset from the database
DsBooks1.Clear()
Me.SqlDataAdapter1.Fill(Me.DsBooks1)
'Save the refreshed dataset in Session state agin
Session("DsBooks") = DsBooks1
DataGrid1.DataBind()
End Sub

// C#
private void DataGrid1_UpdateCommand(object source,
System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
dsBooks.BooksRow dr;
//Get a reference to row zero (where the row was inserted)
dr = this.dsBooks1.Books[0];
TextBox tb1 = (TextBox) e.Item.Cells[2].Controls[0];
dr.title = tb1.Text;
CheckBox cb = (CheckBox) e.Item.Cells[3].Controls[1];
dr.instock = cb.Checked;
this.sqlDataAdapter1.Update(this.dsBooks1);
DataGrid1.EditItemIndex = -1;
//Refresh the dataset from the database
dsBooks1.Clear();
this.sqlDataAdapter1.Fill(this.dsBooks1);
//Save the refreshed dataset in Session state agin
Session["DsBooks"] = dsBooks1;
DataGrid1.DataBind();
}


Thank you, Mike
Microsoft, ASP.NET Support Professional

Microsoft highly recommends to all of our customers that they visit the
http://www.microsoft.com/protect site and perform the three straightforward
steps listed to improve your computer’s security.

This posting is provided "AS IS", with no warranties, and confers no rights.


--------------------
 
J

Jim Heavey

Thanks, but I was not looking for an example of how to
add a row to the datasource, but rather, I was looking
for how to trigger the adding of a row. I realize that I
could add a button to the form, but I thought it would be
much more visually appealing to add a button to the
footer and my question was how to do this.

Sorry for the confusion.
-----Original Message-----
Hi Jim,

There's an article that addresses this subject.

Top Questions about the DataGrid Web Server Control
http://msdn.microsoft.com/library/en- us/dv_vstechart/html/vbtchTopQuestionsA
boutASPNETDataGridServerControl.asp

Here is the relevant section.

Adding Columns Dynamically
You can hide and show columns if you know in advance what columns you need.
Sometimes, however, you do not know that until run time. In that case, you
can create columns dynamically and add them to the grid.

To do so, you create an instance of one of the column classes supported by
the grid - BoundColumn, EditCommandColumn, ButtonColumn, or
HyperlinkColumn. (You can add template columns to the grid, but it is
slightly more complex. For details, see Creating Web Server Control
Templates Programmatically.) Set the column's properties, and then add it
to the grid's Columns collection.

The following example shows how to add two bound columns to a grid.

' Visual Basic
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
'Set data-binding properties of the grid
DataGrid1.AutoGenerateColumns = False
DataGrid1.DataSource = Me.dsBooks1
DataGrid1.DataMember = "Books"
DataGrid1.DataKeyField = "bookid"

' Add two columns
Dim dgc_id As New BoundColumn()
dgc_id.DataField = "bookid"
dgc_id.HeaderText = "ID"
dgc_id.ItemStyle.Width = New Unit(80)
DataGrid1.Columns.Add(dgc_id)

Dim dgc_title As New BoundColumn()
dgc_title.DataField = "title"
dgc_title.HeaderText = "Title"
DataGrid1.Columns.Add(dgc_title)

Me.SqlDataAdapter1.Fill(Me.dsBooks1)
DataGrid1.DataBind()
End Sub

// C#
private void Button1_Click(object sender, System.EventArgs e)
{
DataGrid1.AutoGenerateColumns = false;
DataGrid1.DataSource = this.dsBooks1;
DataGrid1.DataMember = "Books";
DataGrid1.DataKeyField = "bookid";

// Add two columns
BoundColumn dgc_id = new BoundColumn();
dgc_id.DataField = "bookid";
dgc_id.HeaderText = "ID";
dgc_id.ItemStyle.Width = new Unit(80);
DataGrid1.Columns.Add(dgc_id);

BoundColumn dgc_title= new BoundColumn();
dgc_title.DataField = "title";
dgc_title.HeaderText = "Title";
DataGrid1.Columns.Add(dgc_title);

this.sqlDataAdapter1.Fill(this.dsBooks1);
DataGrid1.DataBind();
}
Any time that you add controls to a page dynamically, you have the problem
of persistence. Dynamically-added controls (or in this case, columns) are
not automatically added to the page's view state, so you are obliged to add
logic to the page to make sure the columns are available with each round
trip.

An excellent way to do this is to override the page's LoadViewState method,
which gives you an early opportunity to reestablish columns in the DataGrid
control. Because the LoadViewState method is called before the Page_Load
event is raised, re-adding columns in the LoadViewState method assures that
they are available for normal manipulation by the time any event code runs.

The following example shows how you would expand the previous example to
restore the columns each time the page runs again. As before, the
Button1_Click handler adds two columns to the grid. (In this example, the
event handler calls a separate routine called AddColumns to do so.) In
addition, the page contains a simple Boolean property called
DynamicColumnsAdded indicating whether the grid has had columns added; the
property persists its value in view state. The LoadViewState method first
calls the base class's LoadViewState method, which extracts view state
information and configures controls with it. If columns were previously
added to the grid (as per the DynamicColumnsAdded property), the method
then re-adds them.

' Visual Basic
Private Property DynamicColumnAdded() As Boolean
Get
If ViewState("ColumnAdded") Is Nothing Then
Return False
Else
Return True
End If
End Get
Set(ByVal Value As Boolean)
ViewState("ColumnAdded") = Value
End Set
End Property

Protected Overrides Sub LoadViewState(ByVal savedState As Object)
MyBase.LoadViewState(savedState)
If Me.DynamicColumnAdded Then
Me.AddColums()
End If
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
' Check property to be sure columns are not added more than once
If Me.DynamicColumnAdded Then
Return
Else
Me.AddColums()
End If
End Sub

Protected Sub AddColums()
' Add two columns
Dim dgc_id As New BoundColumn()
dgc_id.DataField = "instock"
dgc_id.HeaderText = "In Stock?"
dgc_id.ItemStyle.Width = New Unit(80)
DataGrid1.Columns.Add(dgc_id)

Dim dgc_title As New BoundColumn()
dgc_title.DataField = "title"
dgc_title.HeaderText = "Title"
DataGrid1.Columns.Add(dgc_title)
Me.DataGrid1.DataBind()
Me.DynamicColumnAdded = True
End Sub

// C#
private bool DynamicColumnAdded{
get
{
object b = ViewState["DynamicColumnAdded"];
return (b == null) ? false : true;
}
set
{
ViewState["DynamicColumnAdded"] = value;
}
}

protected override void LoadViewState(object savedState)
{
base.LoadViewState(savedState);
if (DynamicColumnAdded)
{
this.AddColumns();
}
}

private void Button1_Click(object sender, System.EventArgs e)
{
if(this.DynamicColumnAdded != true)
{
this.AddColumns();
}
}

private void AddColumns()
{
BoundColumn dgc_id = new BoundColumn();
dgc_id.DataField = "bookid";
dgc_id.HeaderText = "ID";
dgc_id.ItemStyle.Width = new Unit(80);
DataGrid1.Columns.Add(dgc_id);

BoundColumn dgc_title= new BoundColumn();
dgc_title.DataField = "title";
dgc_title.HeaderText = "Title";
DataGrid1.Columns.Add(dgc_title);

this.sqlDataAdapter1.Fill(this.dsBooks1);
DataGrid1.DataBind();
this.DynamicColumnAdded = true;
}
Adding New Records to a Data Source Using the DataGrid Control
The DataGrid control allows users to view and edit records, but does not
inherently include the facility to add new ones. However, you can add this
functionality in various ways, all of which involve the following:

Adding a new, blank record to the data source of the grid (in the dataset
or database). If necessary, you will need to assign an ID for the record
and put placeholder values into it for any columns that cannot be null.
Rebinding the DataGrid control to the source.
Putting the grid into edit mode for the new record. You need to be able to
determine where in the grid the new record appears.
Updating the record normally when the user clicks Update, thereby writing
the new record to the source with user-provided values.
The following example shows the process for adding the new record, binding
the grid, and putting it into edit mode. In this example, the data source
is a dataset (DsBooks1 or dsBooks1) containing a table called "Books."

' Visual Basic
Private Sub btnAddRow_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnAddRow.Click
Dim dr As DataRow = Me.DsBooks1.Books.NewRow
dr("title") = "(New)"
dr("instock") = True
Me.DsBooks1.Books.Rows.InsertAt(dr, 0)
Session("DsBooks") = DsBooks1
DataGrid1.EditItemIndex = 0
DataGrid1.DataBind()
End Sub

// C#
private void btnAddRow_Click(object sender, System.EventArgs e)
{
DataRow dr = this.dsBooks1.Books.NewRow();
dr["title"] = "(New)";
dr["instock"] = true;
this.dsBooks1.Books.Rows.InsertAt(dr, 0);
Session["DsBooks"] = dsBooks1;
DataGrid1.EditItemIndex = 0;
DataGrid1.DataBind();
}
Some things to notice:

This code runs when a user clicks an Add button somewhere in the page.
The new row is created using the NewRow method. It is then inserted into
the dataset table using the InsertAt method, which allows you to place it
at a specific, predefined location - in this case, as the first record in
the table (that is, the first record in the Rows collection).
Alternatively, you could add it to the end of the table, using the row
count as the value. The important thing is that you know exactly where the
row is in the table.
Because you know that the record is in the first position of the table, you
can set the grid's EditItemIndex value to zero to put the new row into edit
mode. (If you created the row elsewhere in the table, you would set
EditItemIndex to that location instead.)
Because you have a new record in the dataset (but not yet in the database),
you have to keep a copy of the dataset between round trips - you do not
want to refill it from the database and lose the new record. Here, the code
stores it in Session state. You need to reload the dataset from Session
state when the page loads. The following example shows what your Page_Load
handler might look like:
' Visual Basic
Private Sub Page_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
If Me.IsPostBack Then
DsBooks1 = CType(Session("DsBooks"), dsBooks)
Else
Me.SqlDataAdapter1.Fill(Me.DsBooks1)
Session("DsBooks") = DsBooks1
DataGrid1.DataBind()
End If
End Sub

// C#
private void Page_Load(object sender, System.EventArgs e)
{
if(this.IsPostBack)
{
dsBooks1 = (dsBooks) Session["DsBooks"];
}
else
{
this.sqlDataAdapter1.Fill(this.dsBooks1);
Session["DsBooks"] = dsBooks1;
this.DataGrid1.DataBind();
}
}
For information about maintaining state, see Web Forms State Management in
the Visual Studio documentation.

You can update the record normally. For an example, see Walkthrough: Using
a DataGrid Web Control to Read and Write Data in the Visual Studio
documentation. After updating the dataset, update the database, then
refresh the dataset. Be sure to save the refreshed dataset to Session state
again. Here is an example of an update handler:

' Visual Basic
Private Sub DataGrid1_UpdateCommand(ByVal source As Object, _
ByVal e As
System.Web.UI.WebControls.DataGridCommandEventArgs) _
Handles DataGrid1.UpdateCommand
Dim dr As Dataset.BooksRow
'Get a reference to row zero (where the row was inserted)
dr = Me.DsBooks1.Books(0)
Dim tb As TextBox = CType(e.Item.Cells(2).Controls (0), TextBox)
dr.title = tb.Text
Dim cb As CheckBox = CType(e.Item.Cells(3).Controls (1), CheckBox)
dr.instock = cb.Checked
Me.SqlDataAdapter1.Update(Me.DsBooks1)
DataGrid1.EditItemIndex = -1
'Refresh the dataset from the database
DsBooks1.Clear()
Me.SqlDataAdapter1.Fill(Me.DsBooks1)
'Save the refreshed dataset in Session state agin
Session("DsBooks") = DsBooks1
DataGrid1.DataBind()
End Sub

// C#
private void DataGrid1_UpdateCommand(object source,
System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
dsBooks.BooksRow dr;
//Get a reference to row zero (where the row was inserted)
dr = this.dsBooks1.Books[0];
TextBox tb1 = (TextBox) e.Item.Cells[2].Controls[0];
dr.title = tb1.Text;
CheckBox cb = (CheckBox) e.Item.Cells[3].Controls[1];
dr.instock = cb.Checked;
this.sqlDataAdapter1.Update(this.dsBooks1);
DataGrid1.EditItemIndex = -1;
//Refresh the dataset from the database
dsBooks1.Clear();
this.sqlDataAdapter1.Fill(this.dsBooks1);
//Save the refreshed dataset in Session state agin
Session["DsBooks"] = dsBooks1;
DataGrid1.DataBind();
}


Thank you, Mike
Microsoft, ASP.NET Support Professional

Microsoft highly recommends to all of our customers that they visit the
http://www.microsoft.com/protect site and perform the three straightforward
steps listed to improve your computer's security.

This posting is provided "AS IS", with no warranties, and confers no rights.


--------------------
Content-Class: urn:content-classes:message
From: "Jim Heavey"
Sender: "Jim Heavey"
Subject: DataGrid - Adding Rows
Date: Thu, 13 Nov 2003 05:46:54 -0800
Lines: 5
Message-ID: <[email protected]>
MIME-Version: 1.0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
X-Newsreader: Microsoft CDO for Windows 2000
Thread-Index: AcOp7JlDGa9FRO6BRD68/L+nUe3T9Q==
X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300
Newsgroups: microsoft.public.dotnet.framework.aspnet
Path: cpmsftngxa06.phx.gbl
Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.framework.aspnet:190635
NNTP-Posting-Host: TK2MSFTNGXA09 10.40.1.161
X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet

Trying to figure out the technique which should be used
to add rows to a datagrid. I am thinking that I would
want an "Add" button on the footer, but I am not quite
sure how to do that. Is that the best method? Do you
have a sample of how to do this?

.
 
M

Mike Moore [MSFT]

Hi Jim,

I couldn't find any direct way to do what you want. However, I did find a
workaround using a hidden field. Here's my sample code which uses the Pubs
database.

The HTML

A grid with one template column & a button in the footer template of that
column. Then a hidden field named "h" with runat=server.

<form id="Form1" method="post" runat="server">
<asp:DataGrid id="DataGrid1" runat="server" ShowFooter="True">
<Columns>
<asp:TemplateColumn>
<FooterTemplate>
<asp:Button id="Button1" runat="server"
Text="Button"></asp:Button>
</FooterTemplate>
</asp:TemplateColumn>
</Columns>
</asp:DataGrid><INPUT type="hidden" id="h" runat="server">
</form>

The Code-Behind

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
If Not IsPostBack Then
Bind()
Else
Response.Write(h.Value)
h.Value = ""
End If
End Sub

Private Sub Bind()
Dim Qry1 As System.Data.SqlClient.SqlDataReader
Dim connectionString As String = "server='localhost';
trusted_connection=true; Database='pubs'"
Dim sqlConnection As System.Data.SqlClient.SqlConnection = New
System.Data.SqlClient.SqlConnection(connectionString)
Dim queryString As String = "SELECT au_id, au_lname, au_fname FROM
authors"
Dim sqlCommand As System.Data.SqlClient.SqlCommand = New
System.Data.SqlClient.SqlCommand(queryString, sqlConnection)
sqlConnection.Open()
Qry1 =
sqlCommand.ExecuteReader(System.Data.CommandBehavior.CloseConnection)
DataGrid1.DataSource = Qry1
DataGrid1.DataBind()
Qry1.Close()
sqlCommand.Dispose()
sqlConnection.Close()
sqlConnection.Dispose()
End Sub

Private Sub DataGrid1_ItemDataBound(ByVal sender As Object, ByVal e As
System.Web.UI.WebControls.DataGridItemEventArgs) Handles
DataGrid1.ItemDataBound
If e.Item.ItemType = ListItemType.Footer Then
CType(e.Item.Cells(0).Controls(1),
WebControls.Button).Attributes.Add("onclick", "document.all('h').value =
'click'")
End If
End Sub


Thank you, Mike
Microsoft, ASP.NET Support Professional

Microsoft highly recommends to all of our customers that they visit the
http://www.microsoft.com/protect site and perform the three straightforward
steps listed to improve your computer’s security.

This posting is provided "AS IS", with no warranties, and confers no rights.


--------------------
Content-Class: urn:content-classes:message
From: "Jim Heavey" <[email protected]>
Sender: "Jim Heavey" <[email protected]>
References: <[email protected]>
Subject: RE: DataGrid - Adding Rows
Date: Thu, 13 Nov 2003 12:01:36 -0800
Lines: 461
Message-ID: <[email protected]>
MIME-Version: 1.0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
X-Newsreader: Microsoft CDO for Windows 2000
X-MIMEOLE: Produced By Microsoft MimeOLE V5.50.4910.0300
Thread-Index: AcOqIPGTqfIjfLQnRFuR4w0rvk/WVA==
Newsgroups: microsoft.public.dotnet.framework.aspnet
Path: cpmsftngxa06.phx.gbl
Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.framework.aspnet:190753
NNTP-Posting-Host: TK2MSFTNGXA11 10.40.1.163
X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet

Thanks, but I was not looking for an example of how to
add a row to the datasource, but rather, I was looking
for how to trigger the adding of a row. I realize that I
could add a button to the form, but I thought it would be
much more visually appealing to add a button to the
footer and my question was how to do this.

Sorry for the confusion.
-----Original Message-----
Hi Jim,

There's an article that addresses this subject.

Top Questions about the DataGrid Web Server Control
http://msdn.microsoft.com/library/en- us/dv_vstechart/html/vbtchTopQuestionsA
boutASPNETDataGridServerControl.asp

Here is the relevant section.

Adding Columns Dynamically
You can hide and show columns if you know in advance what columns you need.
Sometimes, however, you do not know that until run time. In that case, you
can create columns dynamically and add them to the grid.

To do so, you create an instance of one of the column classes supported by
the grid - BoundColumn, EditCommandColumn, ButtonColumn, or
HyperlinkColumn. (You can add template columns to the grid, but it is
slightly more complex. For details, see Creating Web Server Control
Templates Programmatically.) Set the column's properties, and then add it
to the grid's Columns collection.

The following example shows how to add two bound columns to a grid.

' Visual Basic
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
'Set data-binding properties of the grid
DataGrid1.AutoGenerateColumns = False
DataGrid1.DataSource = Me.dsBooks1
DataGrid1.DataMember = "Books"
DataGrid1.DataKeyField = "bookid"

' Add two columns
Dim dgc_id As New BoundColumn()
dgc_id.DataField = "bookid"
dgc_id.HeaderText = "ID"
dgc_id.ItemStyle.Width = New Unit(80)
DataGrid1.Columns.Add(dgc_id)

Dim dgc_title As New BoundColumn()
dgc_title.DataField = "title"
dgc_title.HeaderText = "Title"
DataGrid1.Columns.Add(dgc_title)

Me.SqlDataAdapter1.Fill(Me.dsBooks1)
DataGrid1.DataBind()
End Sub

// C#
private void Button1_Click(object sender, System.EventArgs e)
{
DataGrid1.AutoGenerateColumns = false;
DataGrid1.DataSource = this.dsBooks1;
DataGrid1.DataMember = "Books";
DataGrid1.DataKeyField = "bookid";

// Add two columns
BoundColumn dgc_id = new BoundColumn();
dgc_id.DataField = "bookid";
dgc_id.HeaderText = "ID";
dgc_id.ItemStyle.Width = new Unit(80);
DataGrid1.Columns.Add(dgc_id);

BoundColumn dgc_title= new BoundColumn();
dgc_title.DataField = "title";
dgc_title.HeaderText = "Title";
DataGrid1.Columns.Add(dgc_title);

this.sqlDataAdapter1.Fill(this.dsBooks1);
DataGrid1.DataBind();
}
Any time that you add controls to a page dynamically, you have the problem
of persistence. Dynamically-added controls (or in this case, columns) are
not automatically added to the page's view state, so you are obliged to add
logic to the page to make sure the columns are available with each round
trip.

An excellent way to do this is to override the page's LoadViewState method,
which gives you an early opportunity to reestablish columns in the DataGrid
control. Because the LoadViewState method is called before the Page_Load
event is raised, re-adding columns in the LoadViewState method assures that
they are available for normal manipulation by the time any event code runs.

The following example shows how you would expand the previous example to
restore the columns each time the page runs again. As before, the
Button1_Click handler adds two columns to the grid. (In this example, the
event handler calls a separate routine called AddColumns to do so.) In
addition, the page contains a simple Boolean property called
DynamicColumnsAdded indicating whether the grid has had columns added; the
property persists its value in view state. The LoadViewState method first
calls the base class's LoadViewState method, which extracts view state
information and configures controls with it. If columns were previously
added to the grid (as per the DynamicColumnsAdded property), the method
then re-adds them.

' Visual Basic
Private Property DynamicColumnAdded() As Boolean
Get
If ViewState("ColumnAdded") Is Nothing Then
Return False
Else
Return True
End If
End Get
Set(ByVal Value As Boolean)
ViewState("ColumnAdded") = Value
End Set
End Property

Protected Overrides Sub LoadViewState(ByVal savedState As Object)
MyBase.LoadViewState(savedState)
If Me.DynamicColumnAdded Then
Me.AddColums()
End If
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
' Check property to be sure columns are not added more than once
If Me.DynamicColumnAdded Then
Return
Else
Me.AddColums()
End If
End Sub

Protected Sub AddColums()
' Add two columns
Dim dgc_id As New BoundColumn()
dgc_id.DataField = "instock"
dgc_id.HeaderText = "In Stock?"
dgc_id.ItemStyle.Width = New Unit(80)
DataGrid1.Columns.Add(dgc_id)

Dim dgc_title As New BoundColumn()
dgc_title.DataField = "title"
dgc_title.HeaderText = "Title"
DataGrid1.Columns.Add(dgc_title)
Me.DataGrid1.DataBind()
Me.DynamicColumnAdded = True
End Sub

// C#
private bool DynamicColumnAdded{
get
{
object b = ViewState["DynamicColumnAdded"];
return (b == null) ? false : true;
}
set
{
ViewState["DynamicColumnAdded"] = value;
}
}

protected override void LoadViewState(object savedState)
{
base.LoadViewState(savedState);
if (DynamicColumnAdded)
{
this.AddColumns();
}
}

private void Button1_Click(object sender, System.EventArgs e)
{
if(this.DynamicColumnAdded != true)
{
this.AddColumns();
}
}

private void AddColumns()
{
BoundColumn dgc_id = new BoundColumn();
dgc_id.DataField = "bookid";
dgc_id.HeaderText = "ID";
dgc_id.ItemStyle.Width = new Unit(80);
DataGrid1.Columns.Add(dgc_id);

BoundColumn dgc_title= new BoundColumn();
dgc_title.DataField = "title";
dgc_title.HeaderText = "Title";
DataGrid1.Columns.Add(dgc_title);

this.sqlDataAdapter1.Fill(this.dsBooks1);
DataGrid1.DataBind();
this.DynamicColumnAdded = true;
}
Adding New Records to a Data Source Using the DataGrid Control
The DataGrid control allows users to view and edit records, but does not
inherently include the facility to add new ones. However, you can add this
functionality in various ways, all of which involve the following:

Adding a new, blank record to the data source of the grid (in the dataset
or database). If necessary, you will need to assign an ID for the record
and put placeholder values into it for any columns that cannot be null.
Rebinding the DataGrid control to the source.
Putting the grid into edit mode for the new record. You need to be able to
determine where in the grid the new record appears.
Updating the record normally when the user clicks Update, thereby writing
the new record to the source with user-provided values.
The following example shows the process for adding the new record, binding
the grid, and putting it into edit mode. In this example, the data source
is a dataset (DsBooks1 or dsBooks1) containing a table called "Books."

' Visual Basic
Private Sub btnAddRow_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnAddRow.Click
Dim dr As DataRow = Me.DsBooks1.Books.NewRow
dr("title") = "(New)"
dr("instock") = True
Me.DsBooks1.Books.Rows.InsertAt(dr, 0)
Session("DsBooks") = DsBooks1
DataGrid1.EditItemIndex = 0
DataGrid1.DataBind()
End Sub

// C#
private void btnAddRow_Click(object sender, System.EventArgs e)
{
DataRow dr = this.dsBooks1.Books.NewRow();
dr["title"] = "(New)";
dr["instock"] = true;
this.dsBooks1.Books.Rows.InsertAt(dr, 0);
Session["DsBooks"] = dsBooks1;
DataGrid1.EditItemIndex = 0;
DataGrid1.DataBind();
}
Some things to notice:

This code runs when a user clicks an Add button somewhere in the page.
The new row is created using the NewRow method. It is then inserted into
the dataset table using the InsertAt method, which allows you to place it
at a specific, predefined location - in this case, as the first record in
the table (that is, the first record in the Rows collection).
Alternatively, you could add it to the end of the table, using the row
count as the value. The important thing is that you know exactly where the
row is in the table.
Because you know that the record is in the first position of the table, you
can set the grid's EditItemIndex value to zero to put the new row into edit
mode. (If you created the row elsewhere in the table, you would set
EditItemIndex to that location instead.)
Because you have a new record in the dataset (but not yet in the database),
you have to keep a copy of the dataset between round trips - you do not
want to refill it from the database and lose the new record. Here, the code
stores it in Session state. You need to reload the dataset from Session
state when the page loads. The following example shows what your Page_Load
handler might look like:
' Visual Basic
Private Sub Page_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
If Me.IsPostBack Then
DsBooks1 = CType(Session("DsBooks"), dsBooks)
Else
Me.SqlDataAdapter1.Fill(Me.DsBooks1)
Session("DsBooks") = DsBooks1
DataGrid1.DataBind()
End If
End Sub

// C#
private void Page_Load(object sender, System.EventArgs e)
{
if(this.IsPostBack)
{
dsBooks1 = (dsBooks) Session["DsBooks"];
}
else
{
this.sqlDataAdapter1.Fill(this.dsBooks1);
Session["DsBooks"] = dsBooks1;
this.DataGrid1.DataBind();
}
}
For information about maintaining state, see Web Forms State Management in
the Visual Studio documentation.

You can update the record normally. For an example, see Walkthrough: Using
a DataGrid Web Control to Read and Write Data in the Visual Studio
documentation. After updating the dataset, update the database, then
refresh the dataset. Be sure to save the refreshed dataset to Session state
again. Here is an example of an update handler:

' Visual Basic
Private Sub DataGrid1_UpdateCommand(ByVal source As Object, _
ByVal e As
System.Web.UI.WebControls.DataGridCommandEventArgs) _
Handles DataGrid1.UpdateCommand
Dim dr As Dataset.BooksRow
'Get a reference to row zero (where the row was inserted)
dr = Me.DsBooks1.Books(0)
Dim tb As TextBox = CType(e.Item.Cells(2).Controls (0), TextBox)
dr.title = tb.Text
Dim cb As CheckBox = CType(e.Item.Cells(3).Controls (1), CheckBox)
dr.instock = cb.Checked
Me.SqlDataAdapter1.Update(Me.DsBooks1)
DataGrid1.EditItemIndex = -1
'Refresh the dataset from the database
DsBooks1.Clear()
Me.SqlDataAdapter1.Fill(Me.DsBooks1)
'Save the refreshed dataset in Session state agin
Session("DsBooks") = DsBooks1
DataGrid1.DataBind()
End Sub

// C#
private void DataGrid1_UpdateCommand(object source,
System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
dsBooks.BooksRow dr;
//Get a reference to row zero (where the row was inserted)
dr = this.dsBooks1.Books[0];
TextBox tb1 = (TextBox) e.Item.Cells[2].Controls[0];
dr.title = tb1.Text;
CheckBox cb = (CheckBox) e.Item.Cells[3].Controls[1];
dr.instock = cb.Checked;
this.sqlDataAdapter1.Update(this.dsBooks1);
DataGrid1.EditItemIndex = -1;
//Refresh the dataset from the database
dsBooks1.Clear();
this.sqlDataAdapter1.Fill(this.dsBooks1);
//Save the refreshed dataset in Session state agin
Session["DsBooks"] = dsBooks1;
DataGrid1.DataBind();
}


Thank you, Mike
Microsoft, ASP.NET Support Professional

Microsoft highly recommends to all of our customers that they visit the
http://www.microsoft.com/protect site and perform the three straightforward
steps listed to improve your computer's security.

This posting is provided "AS IS", with no warranties, and confers no rights.


--------------------
Content-Class: urn:content-classes:message
From: "Jim Heavey"
Sender: "Jim Heavey"
Subject: DataGrid - Adding Rows
Date: Thu, 13 Nov 2003 05:46:54 -0800
Lines: 5
Message-ID: <[email protected]>
MIME-Version: 1.0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
X-Newsreader: Microsoft CDO for Windows 2000
Thread-Index: AcOp7JlDGa9FRO6BRD68/L+nUe3T9Q==
X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300
Newsgroups: microsoft.public.dotnet.framework.aspnet
Path: cpmsftngxa06.phx.gbl
Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.framework.aspnet:190635
NNTP-Posting-Host: TK2MSFTNGXA09 10.40.1.161
X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet

Trying to figure out the technique which should be used
to add rows to a datagrid. I am thinking that I would
want an "Add" button on the footer, but I am not quite
sure how to do that. Is that the best method? Do you
have a sample of how to do this?

.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,015
Latest member
AmbrosePal

Latest Threads

Top