Web Forms DataGrid and DataSet Programming

Deleting a Row

Deleting a row is fairly straightforward except for paging errors. The DataGrid has built in support for deletions with the OnDeleteCommand property. You simply edit the DataGrid tags and set the delete event handler using the OnDeleteCommand property. The DataGrid will register your event handler. You then must add your delete event handler to the WebForm1.aspx.cs file. You need to implement special logic if the deleted row is the only row on the last page.

Register the Delete Event Handler

If you look at the file WebForm1.aspx in the HTML view you will see where the OnDeleteCommand property is set to "DataGrid_Delete". The DataGrid will use this property to register the delete event handler:

<asp:datagrid id=DataGrid1 style="Z-INDEX: 101; LEFT: 23px; POSITION: absolute; TOP: 221px" runat="server"
DataKeyField="au_id" DataSource="<%# view %>" Height="270px" Width="679px"
OnUpdateCommand="DataGrid1_Update" OnCancelCommand="DataGrid1_Cancel" OnEditCommand="DataGrid1_Edit"
OnDeleteCommand="DataGrid1_Delete" BorderColor="Blue" OnItemCommand="Item_Click" AllowSorting="True"
OnSortCommand="DataGrid1_Sort"
AllowPaging="True" OnPageIndexChanged="DataGrid1_Page" BackColor="#C0FFFF">

Add a Delete Button to the DataGrid

Using the Design view, you can add a "Delete" button to the DataGrid by right clicking on the DataGrid and choosing the property builder. Under "Columns", expand the "Available Column" "Button Column". You will see a "Delete" button that can be added to the "Selected Columns". Don't forget to "Apply" any changes.

Add the Event Handler to WebForm1.aspx.cs

Finally, you need to add the Delete event handler with the proper signature to the WebForm1.asp.cs file. Here is the latest implementation of DataGrid1_Delete (code in red is new):

protected void DataGrid1_Delete(Object sender, DataGridCommandEventArgs e)
{
    string key = DataGrid1.DataKeys[e.Item.ItemIndex].ToString();
    string debug= "No errors.";
    // Updates the dataset table
    try
    {    
        DataRow dr= dataSet11.authors.FindByau_id(key);
        dr.Delete();
        sqlDataAdapter1.Update(dataSet11);
    }
    catch (Exception exc)
    {
        sqlDataAdapter1.Fill(dataSet11); //if Update fails, refresh dataset
        debug= exc.Message;
    }
    // check for invalid page index
    ResetPageIndex(DataGrid1,view);
    DataGrid1.EditItemIndex = -1;
    DataGrid1.DataBind();
    textBoxMessage.Text= debug;
}

Since the data in the DataGrid may not be synchronized with the data in the DataSet, you must find the proper row in the DataSet using the primary key of the selected row. You can retrieve the selected row's primary key by calling:

string key = DataGrid1.DataKeys[e.Item.ItemIndex].ToString();

This works only if you have declared the primary key field in the DataGrid by setting the "DataKeyField" to "au_id". Once you have the primary key of the selected row in the DataGrid, you can find the corresponding row in the DataSet by calling:

DataRow dr= dataSet11.authors.FindByau_id(key);

You can now delete the selected row in the DataSet by calling:

dr.Delete();

At this point the row is marked for deletion in the DataSet, but the row still exists in the database. You must call Update() to commit the changes to the database:

sqlDataAdapter1.Update(dataSet11);

To avoid paging to a non-existent page, you need to implement some special logic to decrement the page index if the page index is invalid:

// check for invalid page index
ResetPageIndex(DataGrid1,view);

Here again is the ResetPageIndex function:

// ResetPageIndex resets invalid page index to last page
// ASSERT grid and view NOT NULL
protected void ResetPageIndex(DataGrid grid, DataView view)
{
    // check for invalid page index
    if ((grid.CurrentPageIndex != 0) && (((grid.CurrentPageIndex)*grid.PageSize)>= view.Count))
    {
        // invalid so leave at last page
        if ((view.Count % grid.PageSize)== 0)
        { // ends on page border
            grid.CurrentPageIndex= (view.Count/grid.PageSize)-1;
        }
        else // partial page
        {
            grid.CurrentPageIndex= (view.Count/grid.PageSize);
        }
    }
}

You should really call this function in _any_ post back that calls Fill and DataBind. Finally, you call DataBind() to refresh the DataGrid which should now reflect any successful deletions.

DataGrid1.EditItemIndex = -1;
DataGrid1.DataBind();

If the deletion fails, the exceptions will be caught and the error message sent back to the user in a multi-line text box.

Add Client Side JavaScript Support

As a final step, add client side JavaScript support, popping up a MessageBox to confirm a deletion. If the user cancels the MessageBox, the post back should not be executed. Unfortunately, there appears to be a bug in the post back event model when in the Edit mode. In Edit mode, the delete event handler is called even if the user cancels the MessageBox! As a workaround you must disable deletion if the selected row is in Edit mode. I have modified the DataGrid in the sample project so that the delete column is the first column in the grid in the Design View. This was done using the Property Builder:

DataGrid --> Right Click --> Property Builder --> Columns --> Selected Columns --> Delete --> Up Arrow --> Apply

As a first step, add the OnItemCreated event handler (in red) to the asp:datagrid tag:

<asp:datagrid id=DataGrid1 runat="server" DataKeyField="au_id" DataSource="<%# view %>"
OnUpdateCommand="DataGrid1_Update" OnCancelCommand="DataGrid1_Cancel"
OnEditCommand="DataGrid1_Edit" OnDeleteCommand="DataGrid1_Delete"
BorderColor="Blue" OnItemCommand="Item_Click" AllowSorting="True"
OnSortCommand="DataGrid1_Sort" AllowPaging="True" OnItemCreated= "DataGrid1_ItemCreated"
OnPageIndexChanged="DataGrid1_Page" BackColor="#C0FFFF">

You can now dynamically add client side JavaScript code to the first column in the DataGrid. This is done in your DataGrid1_ItemCreated event handler. The following is taken from Jeff Prosise's article Wicked Code in MSDN Magazine (August, 2002). Note the interesting cast to the base class WebControl, not to a LinkButton. This cast should work even if you change the column type to a Button.

// this method FAILS in edit mode due to post back bug which calls
// the delete event handler in edit mode even on cancel!
protected void DataGrid1_ItemCreated(Object sender, DataGridItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
    {
        WebControl button = (WebControl) e.Item.Cells[0].Controls[0];
        button.Attributes.Add("onclick", "return confirm (\"Really? Delete? \");");
    }
}

Here is the actual HTML generated by IIS:

<td><a onclick="return confirm ('Really? Delete? ');"
href="javascript:__doPostBack('DataGrid1:_ctl3:_ctl0','')">Delete</a></td>

Now you need to modify the delete event handler to trap the delete event if the selected row is in edit mode. The added code is in red. This code post a warning to the user, and immediately returns from the delete event handler.

// adds workaround for javascript post back bug by disabling
// the delete event handler if the selected row is in edit mode
protected void DataGrid1_Delete(Object sender, DataGridCommandEventArgs e)
{
    if (DataGrid1.EditItemIndex == e.Item.ItemIndex)
    {
        ResetPageIndex(DataGrid1,view);
        textBoxMessage.Text= "WARNING: Unable to delete record in edit mode!\r
            Please Cancel Edit Mode.";
        return;
    }
    string key = DataGrid1.DataKeys[e.Item.ItemIndex].ToString();
    string debug= "No errors.";
    // Updates the dataset table
    try
    {    
        DataRow dr= dataSet11.authors.FindByau_id(key);
        dr.Delete();
        sqlDataAdapter1.Update(dataSet11);
    }
    catch (Exception exc)
    {
        sqlDataAdapter1.Fill(dataSet11); //if Update fails, refresh dataset
        debug= exc.Message;
    }
    // check for invalid page index
    ResetPageIndex(DataGrid1,view);
    DataGrid1.EditItemIndex = -1;
    DataGrid1.DataBind();
    textBoxMessage.Text= debug;
}

You might also like...

Comments

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“Better train people and risk they leave – than do nothing and risk they stay.” - Anonymous