Edit an Entire DataGrid

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

Scott Mitchell

October 30, 2009

23 Min Read
ITPro Today logo in a gray background | ITPro Today

Displaying data on a Web page is an everyday task for aWeb developer. Fortunately, ASP.NET makes data display a breeze with its dataWeb 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 atdisplaying data, DataGrid offersextended functionality that's not found in DataListor Repeater. Specifically, DataGrid has built-in mechanisms forpaging, sorting, and editing.

Adding sorting, paging, or editing support to a DataGrid is as simple as setting aproperty or two and creating the appropriate event handlers. For example, toprovide editing support for a DataGrid,you simply add an EditCommandColumncolumn to the DataGrid, and createevent handlers for the DataGrid's EditCommand, CancelCommand, and UpdateCommandevents. 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 Edithyperlink generated by the EditCommandColumn.To edit a particular row, the user must click on the appropriate Edithyperlink.


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 becomeseditable (see Figure 2). Notice that the editing interface for each column inthe editable row can differ. For example, the Category column in Figure 2 has adropdown list, whereas the Question column has a TextBox Web control with a width of 75 Columns, as opposedto the shorter TextBox Web controlin the Submitted By column. Realize that the editing interface for each columnin the editable DataGrid row dependson the DataGrid column type. If thecolumn is a BoundColumn, then asimple TextBox Web control is used.If the column is a TemplateColumn,then the HTML content and Web controls in the TemplateColumn's EditItemTemplateis used. In Figure 2, the Submitted By column is generated through a BoundColumn, whereas the Category andQuestion columns are TemplateColumnswith EditItemTemplates. 


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

 

Tweak the DataGrid

One downside to the DataGrid'sediting 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 totalof four DataGrid rows. What he mustdo is click the Edit hyperlink of the first row hewants to edit, make the changes, then click on Update to save them. He thenneeds to repeat this process for the other three rows. All this clicking can befrustrating to users, especially if they typically need to edit many rowsduring each visit.

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


Figure 3: This entire DataGridis editable. When a user clicks the Save Changes button, allchanges are committed to the underlying data store.

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

 

Create an Editable DataGrid

Creating an editable DataGridin 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 EditCommandevent fires when the user clicks on the Edit buttonfor a particular row. Therefore, the EditCommand event handler needs toupdate the DataGrid's EditItemIndex property accordingly, andrebind the data to the DataGrid. Similarly, the UpdateCommandevent fires when the user clicks on the edited row's Updatebutton. The event handler then needs to retrieve the new values the user addsand issue a database UPDATE statement. Following that, it needs to return the DataGrid to its pre-editing state bysetting the EditItemIndex property back to -1. The CancelCommandevent handler merely returns the DataGridto its pre-editing state withoutsaving the changes made; it simply resets EditItemIndex to -1.

Each time the DataGrid'sDataBind method is called, the DataGriditerates through its DataSource, creating a new DataGridItem foreach row in the DataSource. (Each DataGridItem makes up one rowof the DataGrid.) During this creationprocess, the DataGrid checks to seeif the current row index is equal to the EditItemIndex property. If itis, then that row is the row being edited, and the DataGridItem isrendered differently than it would be if it weren't being edited. Specifically,those columns in the DataGridItem that are BoundColumns are rendered as TextBoxWeb controls. TemplateColumns, whichusually have their ItemTemplate rendered, have their EditItemTemplaterendered instead.

When a page developer creates an editable DataGrid, she must decide which editinginterface each column needs. If a column needs only a simple TextBox interface, with no validationor customization of the TextBox, a BoundColumn will suffice. If the columnis 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 aparticular column, then you need to use a TemplateColumnso that a RequiredFieldValidatorcan be added. Figure 2 shows anexample of an editing interface that uses something other than a TextBox. Note that the Categoriescolumn for the editable row is rendered as a dropdown list.

Now that we've discussed the process of creating aneditable DataGrid using the DataGrid's built-in features, let'sturn 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 foreach row, there'd be a single edit button at the top of the DataGrid called Edit All Rows. Clicking on thiswould fire an EditBatchCommand event;then an event handler could set the DataGrid'sBatchUpdate propertyto True, causing all rows to becomeeditable. This would also have the effect of having the Edit All Rows button be replacedby two buttons: UpdateAll Rows and Cancel Batch Update. Similarly,clicking on the UpdateAll Rows button would fire an UpdateBatchCommandevent, while clicking on the CancelBatch Update button would fire the CancelBatchCommandevent. The page developer would then create event handlers for these eventsthat would update the database with the batch of changes in the UpdateBatchCommandevent handler and reset the BatchUpdate propertyto False in the CancelBatchCommandevent handler.

Remember, the properties and events I've just mentioneddon't exist in the DataGrid; I'mjust sharing what I envision the idealsolution 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 examinehow to create a very simple, fully editable DataGrid.

Rather than having the capabilities to make all rowseditable 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 ItemTemplatehas a TextBox Web control (orwhatever Web control is needed to provide the editing interface). To make acolumn read-only, we can use a BoundColumnor a TemplateColumn that doesn'tinclude any sort of editing interface in its ItemTemplate.

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

Next, add a DataGridto the Designer. Give this DataGridfour columns: a BoundColumn whose DataFieldproperty is set to ContactID, and three TemplateColumns. The TemplateColumns' ItemTemplatesmust have a TextBox Web control (seeFigure 4).

                                                                                        ...      

Figure 4: When creating a fully editable DataGrid, all editable columns must usea TemplateColumn. This code snippetshows the definition.

If you've created a standard row-by-row editable DataGrid that required TemplateColumns, the content in the ItemTemplatesshould look familiar. Notice that the TextBox'sText property isassigned 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 ContactNamefield for the corresponding DataSource row.

In the ASP.NET Web page's Page_Load event handler, you need to bind the appropriate data tothe DataGrid. This involves issuinga SELECT statement. Asthis code shows, I've used the Microsoft Data Access Application Block toretrieve 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 thesame results if you use other techniques, such as a custom Data Access Layer orthe System.Data classes directly, tobind the data to the DataGrid. I usethe Data Access Application Blocks whenever possible, because they avoidrepetitious code. If you are unfamiliar with Microsoft's Data AccessApplication Block, check out "Examining the Data Access Application Block" byJohn Jakovich at http://aspnet.4guysfromrolla.com/articles/070203-1.aspx.

Figure 5 shows a screenshot of the FullyEditableDG.aspxWeb page when viewed through a browser. With this simple DataGrid and Page_Loadevent handler, we're already halfway to creating a fully editable DataGrid. All that remains is adding a SaveChanges button that, when clicked, updates the database with the newvalues.


Figure 5: All the rows in this DataGridare editable. The next thing to do is to add a Save Changesbutton.

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

 

Issue Update Statements

Next, add a ButtonWeb control named Save Changes above the DataGrid. Then double-click on thisbutton 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 tothe 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 anUPDATE statement to the database for each row.

Although the code may appear a bit unwieldy, it's ratherstraightforward. At the start of the event handler you create a parameterizedSQL UPDATE statement thatwill be used to update each row of the DataGrid.Next, you create a SqlConnection object,followed by a single SqlCommand objectinstantiation. Then you create a SqlParameter objectfor each of the necessary four parameters.

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

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

While this approach is functional, it can no doubt beimproved for both the end user and page developer. Recall that with thestandard, row-by-row editable DataGrid,all rows are shown in a noneditable form by default. Upon clicking on a row's Editbutton, that particular row becomes editable. It would be nice if the fullyeditable DataGrid exhibited the samebehavior: By default the entire DataGridwas not editable until the userclicked on an EditAll Rows button; at this point all rows would become editable. In thenext section we'll examine how to make this a possibility, and how to simplifythe page developer's job by making the code needed to have the fully editable DataGrid work more like the code neededfor 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 standardrow-by-row editable DataGrid, bothfrom the end user's perspective and from the page developer's perspective. Aswe discussed earlier, the standard editable DataGrid has an Edit button for each row that,when clicked, fires the DataGrid's EditCommandevent. As page developers, we create an event handler for this event and setthe DataGrid's EditItemIndexto the index of the row whose Edit button was clicked, andthen rebind the data. Use similar approaches for the Updateand Cancelbuttons.

It would be useful, then, if we could create a customcontrol that extends the DataGrid'sfunctionality to include events such as EditBatchCommand,UpdateBatchCommand,and CancelBatchCommand,and have buttons such as EditAll Rows, UpdateAll Rows, and CancelBatch Update. This custom control would also need a BatchUpdateproperty that would be analogous to the DataGrid'sEditItemIndex, where EditItemIndexmakes a single row editable, and BatchUpdate is aBoolean 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 methodfires once for each of the DataGrid'srows. Its task is to create a return DataGridIteminstance. Our overridden form of CreateItem checks tosee if the type of row being created is an Itemor AlternatingItem. Ifit'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 firstsetting BatchUpdate to Trueor False and then rebinding the data to the DataGrid, just as toggling the editable row in a row-by-roweditable DataGrid is accomplished bysetting the EditItemIndex andthen rebinding the data to the DataGrid.

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

After some additional thinking, I realized that tying thebuttons to the DataGrid in any formwould limit the page developer when she is designing the page's layout. Thatis, what if the page developer was working on a page that was divided into twocolumns, and she wanted the fully editable DataGridin the right-hand column and the EditAll Rows, UpdateAll Rows, and CancelBatch Update buttons in the left-hand column?

 

EditBar Displays the Buttons

Rather than tie the rendering of the buttons directly tothe EditGrid, I decided to create asecond control, named EditBar, thatwould display the EditAll Rows, UpdateAll Rows, and CancelBatch Update buttons. The EditBar has an EditGridID propertythat needs to be set to the ID of the EditGridon the page on which the EditBaroperates. This association allows for actions in the EditBar to raise events in the EditGrid.For example, when the EditBar's Edit All Rowsbutton is clicked, the associated EditGrid'sEditBatchCommandevent is raised. Further, the EditBar'sdisplay - whether just the EditAll Rows button appears or if the Update All Rows and Cancel Batch Updatebuttons appear - depends on the associated EditGrid'sBatchUpdate value.

The EditGridalso 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 Updatebuttons have been created before the EditGrid's EditBatchCommand, UpdateBatchCommand,or CancelBatchCommandevents fire.

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

To remedy this behavior, I made a public Refreshmethod in the EditBar that rebuildsthe EditBar's control hierarchy.This needs to be called after the EditGrid'sBatchUpdate propertyis toggled in the event handler. Rather than require the page developer to addthis each time he toggles BatchUpdate, Idecided to let the EditGrid have theEditBarID property.If this is specified and an appropriately named control is found on the page,the specified EditBar's Refreshmethod is called whenever the EditGrid'sDataBind method iscalled.

Using the EditBarand EditGrid controls in tandem, apage developer can drop the EditGridand EditBar on the page, set the EditBar's EditGridIDto the EditGrid's IDproperty value, then create event handlers for the EditGrid's EditBatchCommand, UpdateBatchCommand,and CancelBatchCommandevents. Let's look at a complete example of using these two controls to createa fully editable DataGrid.

The downloadable materials accompanying this articlecontain the complete source code for these custom controls (see the end of thisarticle for download details). To run this demo you'll need to download andcompile the EditableDataGrid project. Next, you'll need to create a new ASP.NETWeb application project and add the assembly (the DLLfile) created when compiling the EditableDataGrid project to its Referencesfolder. You can then add the EditGridand EditBar to the Visual Studio.NET Toolbox by right-clicking on the Toolbox and choosing Add/RemoveItems. Doing so will display the Customize Toolbox dialog box. Make surethe .NET Framework Components tab is selected and then click the Browsebutton. 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 ontothe Designer of an ASP.NET Web page (see Figure 7). In this figure, the EditGridcontrol in the Toolbox is circled, as well as the BatchUpdateproperty in the Properties pane. Because EditGridis derived from the DataGridcontrol, you can configure the EditGridin Visual Studio .NET just as you would the DataGrid. That is, you can customize the appearance through theAuto Format dialog box, and customize the styles, columns, paging features, andso on through the Property Builder.


Figure 7: The EditGrid can beadded 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 addfour BoundColumns for the CustomerID,ContactName, ContactTitle,and CompanyName fields.Mark the CustomerID BoundColumn as read-only. The codesnippet in Figure 8 shows the declarative syntax of the EditGrid after adding these four BoundColumns.

                                     

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

Given that we'll need to know the primary key value ofeach row when performing our batch update in the EditGrid's UpdateBatchCommandevent handler, be sure to set the EditGrid'sDataKeyField propertyto 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'veperformed 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 itanywhere in the page. The EditBarhas many stylistic properties that you can configure to tweak the look and feelof the EditBar, such as BackColor,Font, GridLines,CellPadding, and soon. You can also customize the appearance by specifying the text for the Edit All Rows, Update All Rows,and Cancel BatchUpdate buttons, as well as indicating if the buttons should be pushbuttons or link buttons.

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


Figure 9: Here, the EditBarhas been added and configured.

All that remains is to create the event handlers for the EditGrid'sEditBatchCommand, UpdateBatchCommand,and CancelBatchCommandevents. The EditBatchCommandevent handler needs to set the BatchUpdate propertyto 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 BindDatamethod simply binds the database data to the EditGrid. Specifically, it queries the database using the DataAccess Application Block and assigns the resulting SqlDataReaderto the EditGrid's DataSource.It then calls the EditGrid's DataBindmethod. The CancelBatchCommandevent handler does the opposite; it sets BatchUpdateto False and then rebinds the data to the DataGrid:

private void dgCustomers_CancelBatchCommand(  object sender, System.EventArgs e){  dgCustomers.BatchUpdate = False;  BindData();}

The UpdateBatchCommandevent handler requires a bit more work. It must first iterate through the DataGridItemsin the EditGrid, issuing a databaseUPDATE statement for each row. Afterward, it needs to reset the EditGrid back to its prebatch editingstate by setting BatchUpdate to Falseand rebinding. The UpdateBatchCommandevent handler is strikingly similar to the code we examined for updating afully editable DataGrid. Hence, thiscode 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 UpdateBatchCommandevent 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 UpdateBatchCommandevent handler and the code we used earlier for performing a batch update of afully editable DataGrid. First, withthe fully editable DataGrid, recallthat each column was a TemplateColumn;here each column is a BoundColumn.Therefore, the code used to programmatically access the contents of thecolumn'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 UpdateBatchCommandevent 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. Figure11 shows the Web page whenit's first visited. Note that the EditGridis not in batch-update mode. Clicking on the Edit All Rows button in the EditBar, though, posts the page backand renders the EditGrid as fullyeditable (see Figure 12). Atthis point the user can make modifications and then click on the Update All Rowsbutton to commit changes and return to the pre-editing state (see Figure 13).


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

 


Figure 12: The Edit All Rows button has beenclicked, causing all rows of the DataGridto become editable simultaneously.

 


Figure 13: Two rows of the EditGridhave been updated.

 

Conclusion

The ASP.NET DataGridprovides editing capabilities, but only on a row-by-row basis. For situationswhere end users need to edit multiple rows at once, this row-by-row approachcan lead to a lot of excessive clicking, and movements from the keyboard to themouse. 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 containthe Web controls necessary for the column's editing interface.

Another technique for creating a fully editable DataGrid is to build a custom controlderived from the DataGrid class thatallows for all rows to becomeeditable simultaneously. In this article we examined the EditGrid and EditRowcontrols, two custom controls I created to facilitate editing all rows at oncein a programmatic and visual style similar to the DataGrid's default row-by-row editing.

Happy Programming!

The sample codein this article is available for download.

 

Speaker,author, and teacher, Scott Mitchellis the editor and founder of http://www.4GuysFromRolla.com,one of the largest ASP resource sites on the Web. He has been avidly using andwriting about Active Server Pages since January 1998. He's authored several hundredASP-related articles on 4Guys, as well as numerous beginner- and advanced-levelbooks 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.

 

Sign up for the ITPro Today newsletter
Stay on top of the IT universe with commentary, news analysis, how-to's, and tips delivered to your inbox daily.

You May Also Like