Edit an Entire DataGrid

Learn How to Make All the Rows in a DataGrid Simultaneously Editable

Displaying data on a Web page is an everyday task for a Web developer. Fortunately, ASP.NET makes data display a breeze with its data Web controls: DataGrid, DataList, and Repeater. For more information on DataGrid, see "DataGrid Magic " and " Top 10 DataGrid Tips ." Although all three data Web controls are great at displaying data, DataGrid offers extended functionality that's not found in DataList or Repeater. Specifically, DataGrid has built-in mechanisms for paging, sorting, and editing.

Adding sorting, paging, or editing support to a DataGrid is as simple as setting a property or two and creating the appropriate event handlers. For example, to provide editing support for a DataGrid, you simply add an EditCommandColumn column to the DataGrid, and create event handlers for the DataGrid's EditCommand, CancelCommand, and UpdateCommand events. Take a look at an editable DataGrid (see Figure 1). Note that by default each row in the DataGrid simply displays its data, accompanied by an Edit hyperlink generated by the EditCommandColumn. To edit a particular row, the user must click on the appropriate Edit hyperlink.


Figure 1: Here's an example of an editable DataGrid before a specific row has been selected for editing.

Once a user clicks on the DataGrid row's Edit hyperlink, that row becomes editable (see Figure 2). Notice that the editing interface for each column in the editable row can differ. For example, the Category column in Figure 2 has a dropdown list, whereas the Question column has a TextBox Web control with a width of 75 Columns, as opposed to the shorter TextBox Web control in the Submitted By column. Realize that the editing interface for each column in the editable DataGrid row depends on the DataGrid column type. If the column is a BoundColumn, then a simple TextBox Web control is used. If the column is a TemplateColumn, then the HTML content and Web controls in the TemplateColumn's EditItemTemplate is used. In Figure 2, the Submitted By column is generated through a BoundColumn, whereas the Category and Question columns are TemplateColumns with EditItemTemplates. 


Figure 2: In this example, DataGrid row FAQ ID 10 has been selected for editing. The Category column has a dropdown list and the Question and Submitted By columns have TextBox Web controls.

 

Tweak the DataGrid

One downside to the DataGrid's editing capabilities, as Figure 2 illustrates, is that only one DataGrid row can be edited at a time. Imagine for a moment that the user visiting the Web page wants to edit a total of four DataGrid rows. What he must do is click the Edit hyperlink of the first row he wants to edit, make the changes, then click on Update to save them. He then needs to repeat this process for the other three rows. All this clicking can be frustrating to users, especially if they typically need to edit many rows during each visit.

In this article we'll examine how to tweak the DataGrid's editing capabilities to allow for all of a DataGrid's rows to be editable at once. Consider a screenshot of a completely editable DataGrid (see Figure 3). The Save Changes button at the top of the DataGrid will, when clicked, commit all the changes to the DataGrid's underlying data store. Specifically, we'll look at how to provide complete editing capabilities to the CompanyName, ContactName, and ContactTitle columns of the Northwind database's Customers table. (The Northwind database is installed by default with both Microsoft SQL Server 2000 and Microsoft Access.)


Figure 3: This entire DataGrid is editable. When a user clicks the Save Changes button, all changes are committed to the underlying data store.

This article assumes you are familiar with creating editable DataGrids. Next, I'll take a brief, high-level look at the process of creating the standard, single-row editable DataGrid. I won't, however, delve into specifics or examine code. If you need a refresher on creating editable DataGrids using the default, built-in editing capabilities, I encourage you to first read these articles: "Utilizing the DataGrid's Built-In Editing Features" by Scott Mitchell and "Enhancing an Editable DataGrid's Editing Interface" by Scott Mitchell and Matthew Rouse.

 

Create an Editable DataGrid

Creating an editable DataGrid in Visual Studio .NET involves three steps:

  1. Drag and drop a DataGrid from the Toolbox onto the Designer of an open ASP.NET Web page.
  2. Configure the DataGrid so that it includes a Button column with the buttons Edit, Update, and Cancel.
  3. Create event handlers for the DataGrid's EditCommand, UpdateCommand, and CancelCommand events.

The majority of the work is in step 3. The EditCommand event fires when the user clicks on the Edit button for a particular row. Therefore, the EditCommand event handler needs to update the DataGrid's EditItemIndex property accordingly, and rebind the data to the DataGrid. Similarly, the UpdateCommand event fires when the user clicks on the edited row's Update button. The event handler then needs to retrieve the new values the user adds and issue a database UPDATE statement. Following that, it needs to return the DataGrid to its pre-editing state by setting the EditItemIndex property back to -1. The CancelCommand event handler merely returns the DataGrid to its pre-editing state without saving the changes made; it simply resets EditItemIndex to -1.

Each time the DataGrid's DataBind method is called, the DataGrid iterates through its DataSource, creating a new DataGridItem for each row in the DataSource. (Each DataGridItem makes up one row of the DataGrid.) During this creation process, the DataGrid checks to see if the current row index is equal to the EditItemIndex property. If it is, then that row is the row being edited, and the DataGridItem is rendered differently than it would be if it weren't being edited. Specifically, those columns in the DataGridItem that are BoundColumns are rendered as TextBox Web controls. TemplateColumns, which usually have their ItemTemplate rendered, have their EditItemTemplate rendered instead.

When a page developer creates an editable DataGrid, she must decide which editing interface each column needs. If a column needs only a simple TextBox interface, with no validation or customization of the TextBox, a BoundColumn will suffice. If the column is an editing interface that's more advanced than just a simple TextBox, or if it requires validation, then a TemplateColumn must be used, and the advanced editing interface must be specified in the TemplateColumn's EditItemTemplate. For example, if you need to ensure that the user provides a value for a particular column, then you need to use a TemplateColumn so that a RequiredFieldValidator can be added. Figure 2 shows an example of an editing interface that uses something other than a TextBox. Note that the Categories column for the editable row is rendered as a dropdown list.

Now that we've discussed the process of creating an editable DataGrid using the DataGrid's built-in features, let's turn to how to create a fully editable DataGrid.

 

Create a Fully Editable DataGrid

Ideally, a fully editable DataGrid would work similarly to the default DataGrid that's editable row-by-row. Instead of an edit button for each row, there'd be a single edit button at the top of the DataGrid called Edit All Rows. Clicking on this would fire an EditBatchCommand event; then an event handler could set the DataGrid's BatchUpdate property to True, causing all rows to become editable. This would also have the effect of having the Edit All Rows button be replaced by two buttons: Update All Rows and Cancel Batch Update. Similarly, clicking on the Update All Rows button would fire an UpdateBatchCommand event, while clicking on the Cancel Batch Update button would fire the CancelBatchCommand event. The page developer would then create event handlers for these events that would update the database with the batch of changes in the UpdateBatchCommand event handler and reset the BatchUpdate property to False in the CancelBatchCommand event handler.

Remember, the properties and events I've just mentioned don't exist in the DataGrid; I'm just sharing what I envision the ideal solution would be. Later in this article we'll look at how to create a custom, compiled ASP.NET server control that extends the DataGrid to provide such functionality. But first, let's examine how to create a very simple, fully editable DataGrid.

Rather than having the capabilities to make all rows editable or noneditable, our fully editable DataGrid will always have all rows editable. To accomplish this, all columns that need to be editable will need to be created as TemplateColumns whose ItemTemplate has a TextBox Web control (or whatever Web control is needed to provide the editing interface). To make a column read-only, we can use a BoundColumn or a TemplateColumn that doesn't include any sort of editing interface in its ItemTemplate.

For this example, let's display the ContactID, ContactName, ContactTitle, and CompanyName fields from the first 10 records from the Northwind database's Customers table, making ContactID read-only and the other three fields editable. To do this, create a new ASP.NET Web application project in Visual Studio .NET and add a new ASP.NET Web Form named FullyEditableDG.aspx.

Next, add a DataGrid to the Designer. Give this DataGrid four columns: a BoundColumn whose DataField property is set to ContactID, and three TemplateColumns. The TemplateColumns' ItemTemplates must have a TextBox Web control (see Figure 4).



  

    

    

      

        

        

      

    

    

      

        

        

      

    

    

      ...

    

  

Figure 4: When creating a fully editable DataGrid, all editable columns must use a TemplateColumn. This code snippet shows the definition.

If you've created a standard row-by-row editable DataGrid that required TemplateColumns, the content in the ItemTemplates should look familiar. Notice that the TextBox's Text property is assigned the result of a databinding expression. That is, for each DataGrid row, the TextBox for the Contact Name column will contain the value of the ContactName field for the corresponding DataSource row.

In the ASP.NET Web page's Page_Load event handler, you need to bind the appropriate data to the DataGrid. This involves issuing a SELECT statement. As this code shows, I've used the Microsoft Data Access Application Block to retrieve the data:

private void Page_Load(object sender, System.EventArgs e)

{

  if (!Page.IsPostBack)

  {

    const string SQL = @"SELECT TOP 10 CustomerID, " +

                       "ContactName, ContactTitle, " +

                        "CompanyName FROM Customers";

    dgCustomers.DataSource = SqlHelper.ExecuteReader(

       connectionString, CommandType.Text, SQL);

    dgCustomers.DataBind();

  }

}

However, you can achieve the same results if you use other techniques, such as a custom Data Access Layer or the System.Data classes directly, to bind the data to the DataGrid. I use the Data Access Application Blocks whenever possible, because they avoid repetitious code. If you are unfamiliar with Microsoft's Data Access Application Block, check out "Examining the Data Access Application Block" by John Jakovich at http://aspnet.4guysfromrolla.com/articles/070203-1.aspx.

Figure 5 shows a screenshot of the FullyEditableDG.aspx Web page when viewed through a browser. With this simple DataGrid and Page_Load event handler, we're already halfway to creating a fully editable DataGrid. All that remains is adding a Save Changes button that, when clicked, updates the database with the new values.


Figure 5: All the rows in this DataGrid are editable. The next thing to do is to add a Save Changes button.

To complete this final task, start by setting the DataGrid's DataKeyField property to CustomerID. The DataKeyField property is commonly used in the default editable DataGrid to keep track of each row's primary key value. Because we'll be issuing UPDATE statements for all the rows in the DataGrid, it's imperative that we know the primary key value for each row so the updates are applied correctly. Therefore, we need to use the DataKeyField property.

 

Issue Update Statements

Next, add a Button Web control named Save Changes above the DataGrid. Then double-click on this button in the designer to create a Click event handler. Here we need to write the code that iterates through the DataGrid's DataGridItems and, for each row, issues an UPDATE statement to the database (see Figure 6).

private void btnSaveAll_Click(object sender,

  System.EventArgs e)

{

  // Craft the SQL statement.

  const string SQL = @"UPDATE Customers SET" +

                     "ContactName = @ContactName, " +

                     "ContactTitle = @ContactTitle, " +

                     "CompanyName = @CompanyName" +

                     "WHERE CustomerID = @CustomerID";

  // Establish a connection to the database.

  SqlConnection myConnection =

    new SqlConnection(connectionString);

  myConnection.Open();

  // Create a SqlCommand object.

  SqlCommand myCommand = new SqlCommand(SQL, myConnection);

  // Create the SqlParameter objects.

  SqlParameter customerIDParam = new SqlParameter();

  customerIDParam.ParameterName = "@CustomerID";

 

  SqlParameter contactNameParam = new SqlParameter();

  contactNameParam.ParameterName = "@ContactName";

 

  SqlParameter contactTitleParam = new SqlParameter();

  contactTitleParam.ParameterName = "@ContactTitle";

 

  SqlParameter companyNameParam = new SqlParameter();

  companyNameParam.ParameterName = "@CompanyName";

  // Iterate through the DataGrid's Items.

  foreach(DataGridItem item in dgCustomers.Items)

  {

    myCommand.Parameters.Clear();

    // Assign the values to update.

    customerIDParam.Value =

     (string) dgCustomers.DataKeys[item.ItemIndex];

    contactNameParam.Value =

       ((TextBox)item.Cells[1].FindControl("Name")).Text;

    contactTitleParam.Value =

       ((TextBox)item.Cells[2].FindControl("Title")).Text;

    companyNameParam.Value =

       ((TextBox)item.Cells[3].FindControl("Company")).Text;

    myCommand.Parameters.Add(customerIDParam);

    myCommand.Parameters.Add(contactNameParam);

    myCommand.Parameters.Add(contactTitleParam);

    myCommand.Parameters.Add(companyNameParam);

    // Issue the update.

    myCommand.ExecuteNonQuery();            

  }

  // Close the connection.

  myConnection.Close();

  Response.Write("Your changes have been saved!");

}

Figure 6: This code iterates through the DataGrid's DataGridItems and issues an UPDATE statement to the database for each row.

Although the code may appear a bit unwieldy, it's rather straightforward. At the start of the event handler you create a parameterized SQL UPDATE statement that will be used to update each row of the DataGrid. Next, you create a SqlConnection object, followed by a single SqlCommand object instantiation. Then you create a SqlParameter object for each of the necessary four parameters.

Next, a foreach loop iterates through the rows in the DataGrid. Inside the loop, the SqlCommand's Parameters collection is first cleared out, then populated with the parameters whose values have been updated to the current row's values in the TextBox Web controls. Notice that the customerIDParam SqlParameter's value is read from the DataGrid's DataKeys collection, while the remaining parameters are read from the TextBox Web controls. Note that the TextBox Web controls in the ItemTemplate are referenced through the FindControl method. (For more information on programmatically accessing the contents of a TemplateColumn, check out "Accessing a Particular Row's TemplateColumn's Contents" by Scott Mitchell at http://datawebcontrols.com/faqs/ProgrammaticAccess/AccessingTemplateColumnContents.shtml.)

When a user first visits the FullyEditableDG.aspx Web page she will see a DataGrid where all the rows are editable. At this point, she can make changes to various columns in various rows. When she has completed her batch edits and clicks the Save Changes button, the Web page is posted back and the Button's Click event handler executes. This event handler iterates through the rows of the DataGrid. For each row, it issues an UPDATE statement to the database, thereby committing the user's batch changes.

While this approach is functional, it can no doubt be improved for both the end user and page developer. Recall that with the standard, row-by-row editable DataGrid, all rows are shown in a noneditable form by default. Upon clicking on a row's Edit button, that particular row becomes editable. It would be nice if the fully editable DataGrid exhibited the same behavior: By default the entire DataGrid was not editable until the user clicked on an Edit All Rows button; at this point all rows would become editable. In the next section we'll examine how to make this a possibility, and how to simplify the page developer's job by making the code needed to have the fully editable DataGrid work more like the code needed for the row-by-row editable DataGrid.

 

Create a Fully Editable DataGrid Server Control

Although the fully editable DataGrid we've created works, it's dissimilar to the standard row-by-row editable DataGrid, both from the end user's perspective and from the page developer's perspective. As we discussed earlier, the standard editable DataGrid has an Edit button for each row that, when clicked, fires the DataGrid's EditCommand event. As page developers, we create an event handler for this event and set the DataGrid's EditItemIndex to the index of the row whose Edit button was clicked, and then rebind the data. Use similar approaches for the Update and Cancel buttons.

It would be useful, then, if we could create a custom control that extends the DataGrid's functionality to include events such as EditBatchCommand, UpdateBatchCommand, and CancelBatchCommand, and have buttons such as Edit All Rows, Update All Rows, and Cancel Batch Update. This custom control would also need a BatchUpdate property that would be analogous to the DataGrid's EditItemIndex, where EditItemIndex makes a single row editable, and BatchUpdate is a Boolean value that, when True, makes all the rows editable.

To do this, I started by creating a custom control named EditGrid, which I derived from the DataGrid class (System.Web.UI.WebControls.DataGrid). Initially, I gave this control a single additional property - BatchUpdate - and overrode its CreateItem method:

protected override DataGridItem CreateItem(int itemIndex,

  int dataSourceIndex, ListItemType itemType)

{

  if (itemType == ListItemType.Item ||

      itemType == ListItemType.AlternatingItem)

  {

    if (BatchUpdate)

      return new DataGridItem(itemIndex, dataSourceIndex,

                              ListItemType.EditItem);

  }

  return new DataGridItem(itemIndex, dataSourceIndex,

                          itemType);

}

Realize that the CreateItem method fires once for each of the DataGrid's rows. Its task is to create a return DataGridItem instance. Our overridden form of CreateItem checks to see if the type of row being created is an Item or AlternatingItem. If it's one of these, and BatchUpdate is True, then the row is created as an EditItem instead. With this minor addition, one can toggle whether all rows are editable by first setting BatchUpdate to True or False and then rebinding the data to the DataGrid, just as toggling the editable row in a row-by-row editable DataGrid is accomplished by setting the EditItemIndex and then rebinding the data to the DataGrid.

Next, I wanted to add the Edit All Rows, Update All Rows, and Cancel Batch Update buttons to the EditGrid, but where should they appear? Initially, I overrode the DataGrid's CreateChildControls method and added them to the control hierarchy prior to the DataGrid. This didn't work, however, because the PrepareControlHierachy method, which is called when the DataGrid is rendered, blindly grabs the first control in the control hierarchy, assuming it's the Table control encasing the DataGrid. (Although I could have overridden PrepareControlHierarchy, it would have involved rewriting the entire method.) Adding the buttons at the end of the control hierarchy worked, but it had the effect of placing the buttons after the DataGrid, and I wanted to be able to have them appear before the DataGrid. I considered embedding the buttons in the DataGrid's header or pager rows, but decided this was neither a clean nor ideal solution.

After some additional thinking, I realized that tying the buttons to the DataGrid in any form would limit the page developer when she is designing the page's layout. That is, what if the page developer was working on a page that was divided into two columns, and she wanted the fully editable DataGrid in the right-hand column and the Edit All Rows, Update All Rows, and Cancel Batch Update buttons in the left-hand column?

 

EditBar Displays the Buttons

Rather than tie the rendering of the buttons directly to the EditGrid, I decided to create a second control, named EditBar, that would display the Edit All Rows, Update All Rows, and Cancel Batch Update buttons. The EditBar has an EditGridID property that needs to be set to the ID of the EditGrid on the page on which the EditBar operates. This association allows for actions in the EditBar to raise events in the EditGrid. For example, when the EditBar's Edit All Rows button is clicked, the associated EditGrid's EditBatchCommand event is raised. Further, the EditBar's display - whether just the Edit All Rows button appears or if the Update All Rows and Cancel Batch Update buttons appear - depends on the associated EditGrid's BatchUpdate value.

The EditGrid also contains an optional EditBarID property. Because of the order of events in an ASP.NET page lifecycle, the EditBar's Edit All Rows button or Update All Rows/Cancel Batch Update buttons have been created before the EditGrid's EditBatchCommand, UpdateBatchCommand, or CancelBatchCommand events fire.

Therefore, consider what might happen in the following scenario: The EditGrid's BatchUpdate property is False, so the EditBar is created with only the Edit All Rows button. Now, the user clicks on this button, causing the page to post back. Upon postback, the EditBar notes that the EditGrid's BatchUpdate property is False, so it again is created with just an Edit All Rows button. However, later in the page lifecycle, the EditGrid's EditBatchCommand event fires (given the postback was caused by the user clicking on the Edit All Rows button). Chances are, the page developer will have created an event handler for this event that sets the BatchUpdate property to True and rebinds the EditGrid's data. The problem is that the EditBar still is showing the Edit All Rows button, even though by this point BatchUpdate is True and all rows are being edited.

To remedy this behavior, I made a public Refresh method in the EditBar that rebuilds the EditBar's control hierarchy. This needs to be called after the EditGrid's BatchUpdate property is toggled in the event handler. Rather than require the page developer to add this each time he toggles BatchUpdate, I decided to let the EditGrid have the EditBarID property. If this is specified and an appropriately named control is found on the page, the specified EditBar's Refresh method is called whenever the EditGrid's DataBind method is called.

Using the EditBar and EditGrid controls in tandem, a page developer can drop the EditGrid and EditBar on the page, set the EditBar's EditGridID to the EditGrid's ID property value, then create event handlers for the EditGrid's EditBatchCommand, UpdateBatchCommand, and CancelBatchCommand events. Let's look at a complete example of using these two controls to create a fully editable DataGrid.

The downloadable materials accompanying this article contain the complete source code for these custom controls (see the end of this article for download details). To run this demo you'll need to download and compile the EditableDataGrid project. Next, you'll need to create a new ASP.NET Web application project and add the assembly (the DLL file) created when compiling the EditableDataGrid project to its References folder. You can then add the EditGrid and EditBar to the Visual Studio .NET Toolbox by right-clicking on the Toolbox and choosing Add/Remove Items. Doing so will display the Customize Toolbox dialog box. Make sure the .NET Framework Components tab is selected and then click the Browse button. Navigate to the EditableDataGrid assembly and click OK.

 

Drag the EditGrid Control

At this point you should be able to drag the EditGrid control from the Toolbox onto the Designer of an ASP.NET Web page (see Figure 7). In this figure, the EditGrid control in the Toolbox is circled, as well as the BatchUpdate property in the Properties pane. Because EditGrid is derived from the DataGrid control, you can configure the EditGrid in Visual Studio .NET just as you would the DataGrid. That is, you can customize the appearance through the Auto Format dialog box, and customize the styles, columns, paging features, and so on through the Property Builder.


Figure 7: The EditGrid can be added to the Visual Studio .NET Designer.

The next task facing us is to add the EditGrid's columns. Launch the Property Builder dialog box and add four BoundColumns for the CustomerID, ContactName, ContactTitle, and CompanyName fields. Mark the CustomerID BoundColumn as read-only. The code snippet in Figure 8 shows the declarative syntax of the EditGrid after adding these four BoundColumns.



  

    

    

    

    

    

    

    

    

  

 

Figure 8: This code shows the declarative syntax of the EditGrid after adding four BoundColumns for the CustomerID, ContactName, ContactTitle, and CompanyName fields.

Given that we'll need to know the primary key value of each row when performing our batch update in the EditGrid's UpdateBatchCommand event handler, be sure to set the EditGrid's DataKeyField property to CustomerID. Before moving on, take a moment to use the EditGrid's Auto Format dialog box to improve the appearance of the EditGrid. Notice that so far we've performed the same steps we would take for creating a row-by-row editable DataGrid.

Next, we need to add the EditBar control to the Web page. I am going to add the EditBar immediately above the EditGrid, but feel free to add it anywhere in the page. The EditBar has many stylistic properties that you can configure to tweak the look and feel of the EditBar, such as BackColor, Font, GridLines, CellPadding, and so on. You can also customize the appearance by specifying the text for the Edit All Rows, Update All Rows, and Cancel Batch Update buttons, as well as indicating if the buttons should be push buttons or link buttons.

Of prime importance is the EditBar's EditGridID property. Be sure to set this property to the ID property value of the EditGrid. If you forget to do this, you'll get an exception when visiting the Web page through a browser. At this point be sure to also set the EditGrid's EditBarID property to the ID of the EditBar added. Take a look at a screenshot of Visual Studio .NET after an EditBar has been added and configured (see Figure 9).


Figure 9: Here, the EditBar has been added and configured.

All that remains is to create the event handlers for the EditGrid's EditBatchCommand, UpdateBatchCommand, and CancelBatchCommand events. The EditBatchCommand event handler needs to set the BatchUpdate property to True and rebind the data to the DataGrid. This can be accomplished with the following code:

private void dgCustomers_EditBatchCommand(object sender,

  System.EventArgs e)

{

  dgCustomers.BatchUpdate = True;

  BindData();

}

The BindData method simply binds the database data to the EditGrid. Specifically, it queries the database using the Data Access Application Block and assigns the resulting SqlDataReader to the EditGrid's DataSource. It then calls the EditGrid's DataBind method. The CancelBatchCommand event handler does the opposite; it sets BatchUpdate to False and then rebinds the data to the DataGrid:

private void dgCustomers_CancelBatchCommand(

  object sender, System.EventArgs e)

{

  dgCustomers.BatchUpdate = False;

  BindData();

}

The UpdateBatchCommand event handler requires a bit more work. It must first iterate through the DataGridItems in the EditGrid, issuing a database UPDATE statement for each row. Afterward, it needs to reset the EditGrid back to its prebatch editing state by setting BatchUpdate to False and rebinding. The UpdateBatchCommand event handler is strikingly similar to the code we examined for updating a fully editable DataGrid. Hence, this code has much of the repetition omitted for brevity (see Figure 10).

private void dgCustomers_UpdateBatchCommand(

  object sender, System.EventArgs e)

{

  // craft the SQL statment

  const string SQL = @"UPDATE Customers SET" +

                     "ContactName = @ContactName," +

                     "ContactTitle = @ContactTitle," +

                     "CompanyName = @CompanyName" +

                     "WHERE CustomerID = @CustomerID";

  // Establish a connection to the database.

  ... code omitted for brevity ...

  // Create a SqlCommand object.

  ... code omitted for brevity ...

  // Create the SqlParameter objects.

  ... code omitted for brevity ...

  // Iterate through the DataGrid's Items.

  foreach(DataGridItem item in dgCustomers.Items)

  {

    myCommand.Parameters.Clear();

    // Assign the values to update.

    customerIDParam.Value =

       (string)dgCustomers.DataKeys[item.ItemIndex];

    contactNameParam.Value =

       ((TextBox)item.Cells[1].Controls[0]).Text;

    contactTitleParam.Value =

       ((TextBox)item.Cells[2].Controls[0]).Text;

    companyNameParam.Value =

       ((TextBox)item.Cells[3].Controls[0]).Text;

    myCommand.Parameters.Add(customerIDParam);

    ... code omitted for brevity ...

    // Issue the update.

    myCommand.ExecuteNonQuery();            

  }

  // Close the connection.

  myConnection.Close();

  dgCustomers.BatchUpdate = false;

  BindData();

}

Figure 10: The UpdateBatchCommand event handler iterates through all the DataGridItems. An UPDATE statement is issued for each DataGridItem.

 

Each Column Is a BoundColumn

There are only two differences between the code for the EditGrid's UpdateBatchCommand event handler and the code we used earlier for performing a batch update of a fully editable DataGrid. First, with the fully editable DataGrid, recall that each column was a TemplateColumn; here each column is a BoundColumn. Therefore, the code used to programmatically access the contents of the column's editing interface differs. Here we use item.Cells[index].Controls[0] to refer to the BoundColumn's TextBox. Second, at the end of the UpdateBatchCommand event handler, we reset the BatchUpdate property to False and call BindData.

Take a look at Figures 11, 12, and 13; these three figures illustrate the EditGrid and EditBar in action. Figure 11 shows the Web page when it's first visited. Note that the EditGrid is not in batch-update mode. Clicking on the Edit All Rows button in the EditBar, though, posts the page back and renders the EditGrid as fully editable (see Figure 12). At this point the user can make modifications and then click on the Update All Rows button to commit changes and return to the pre-editing state (see Figure 13).


Figure 11: The EditGrid is in its pre-editing state. All the data is shown in the typical read-only format.

 


Figure 12: The Edit All Rows button has been clicked, causing all rows of the DataGrid to become editable simultaneously.

 


Figure 13: Two rows of the EditGrid have been updated.

 

Conclusion

The ASP.NET DataGrid provides editing capabilities, but only on a row-by-row basis. For situations where end users need to edit multiple rows at once, this row-by-row approach can lead to a lot of excessive clicking, and movements from the keyboard to the mouse. A workaround is to create a fully editable DataGrid, which is done by using TemplateColumns for each of the DataGrid's columns where the TemplateColumns' ItemTemplates contain the Web controls necessary for the column's editing interface.

Another technique for creating a fully editable DataGrid is to build a custom control derived from the DataGrid class that allows for all rows to become editable simultaneously. In this article we examined the EditGrid and EditRow controls, two custom controls I created to facilitate editing all rows at once in a programmatic and visual style similar to the DataGrid's default row-by-row editing.

Happy Programming!

The sample code in this article is available for download.

 

Speaker, author, and teacher, Scott Mitchell is the editor and founder of http://www.4GuysFromRolla.com, one of the largest ASP resource sites on the Web. He has been avidly using and writing about Active Server Pages since January 1998. He's authored several hundred ASP-related articles on 4Guys, as well as numerous beginner- and advanced-level books on Active Server Pages and ASP.NET. Scott can be reached at mailto:[email protected]. You can find his web log at http://ScottOnWriting.NET.

 

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish