Wednesday, January 04, 2006
« ViewState and the Coalescing Operator (?... | Main | ASP.NET, Tilde (~), Virtual Paths and th... »

NOTE: I have slightly modified this post and the associated source. Make sure to take a look at v2 after reading this post:
http://blog.binaryocean.com/PermaLink,guid,a1ff6cab-dc2d-441c-8557-7dce920d4075.aspx

-Andrew

>>>

In ASP.NET version 1.x, I used the footer on the DataGrid control to insert new rows by placing a series of TextBox, DropDownLists, CheckBoxes etc. controls on it and then handling a save button. This also works with the GridView in version 2.0 but with one major exception: if your data source is empty, the GridView will hide your footer (and header) and only display the EmptyDataText.

Conventional wisdom says that you should use a DetailsView to insert rows, but I don't want to shift the user between two different controls. You can edit and delete rows with a GridView so why not Insert?

Here is the solution. I am using an ObjectDataSource control to wire up my data access class. If the DataTable coming back from my data class is empty, I add a null row. This works fine but now you get blank rows in the GridView. To handle that, I hide the rows during the RowCreated event. Lastly, I clear the controls off of the now hidden row so that there are no binding errors as would be the case with a cast boolean value which I do to set the value of a CheckBox in my GridView.

You can download the entire solution and sample database here:
http://download.binaryocean.com/GridViewInsertSolution.zip

private bool LoadDataEmpty

{

    //  some controls that are used within a GridView,

    //  such as the calendar control, can cuase post backs.

    //  we need to preserve LoadDataEmpty across post backs.

    get { return (bool)(ViewState["LoadDataEmpty"] ?? false); }

    set { ViewState["LoadDataEmpty"] = value; }

}

protected void ObjectDataSourceMain_Selected(object sender, ObjectDataSourceStatusEventArgs e)
{
    //  bubble exceptions before we touch e.ReturnValue
   
if (e.Exception != null)
   
{
       
throw e.Exception;
    
}

    // get the DataTable from the ODS select mothod
    DataTable dataTable = (DataTable)e.ReturnValue;

    // if rows=0 then add a dummy (null) row and set the LoadDataEmpty flag.

    if (dataTable.Rows.Count == 0)

    {

        dataTable.Rows.Add(dataTable.NewRow());

        LoadDataEmpty = true;

    }

    else

    {

        LoadDataEmpty = false;

    }

}

 

protected void GridViewMain_RowCreated(object sender, GridViewRowEventArgs e)

{

    // when binding a row, look for a zero row condition based on the flag.

    // if we have zero data rows (but a dummy row), hide the grid view row

    // and clear the controls off of that row so they don't cause binding errors

    if (LoadDataEmpty && e.Row.RowType == DataControlRowType.DataRow)

    {

        e.Row.Visible = false;

        e.Row.Controls.Clear();

    }

}

 

protected void GridViewMain_RowCommand(object sender, GridViewCommandEventArgs e)

{

    // handle the save button on the footer row. this is the only manual data operation

    // that must be done. update and delete are handled by the gridview and ODS

    if (e.CommandName == "Save")

    {

        string code = ((TextBox)GridViewMain.FooterRow.FindControl("TextBoxCode")).Text;

        string description = ((TextBox)GridViewMain.FooterRow.FindControl("TextBoxDescription")).Text;

        bool isActive = ((CheckBox)GridViewMain.FooterRow.FindControl("CheckBoxIsActive")).Checked;

 

        new LocationData().Insert(code, description, isActive);

 

        GridViewMain.DataBind();

    }

}

 

 

kick it on DotNetKicks.com   Wednesday, January 04, 2006 11:02:54 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [16]  |