Click here to Skip to main content
15,884,628 members
Articles / Web Development / ASP.NET
Article

GridView with insert line

Rate me:
Please Sign up or sign in to vote.
4.40/5 (30 votes)
1 Jun 2007CPOL5 min read 437.1K   4.9K   87   102
A GridView with insert line.

Sample Image - grid.gif

Introduction

There are millions of articles written about how to add an insert line to the GridView control. Anything that I got to work more or less suggests to add a FooterRow with appropriate templates. Even that approach breaks apart if the data source is empty - then the GridView just displays an empty line. Both of those problems are addressed in the proposed solution - a HeaderRow is always shown and a FooterRow is automatically populated with appropriate templates/input elements. Also, what sets this solution apart is that no special or additional setup is needed neither for the columns (the use of special types) nor for the footer row or for the data-source/SQL statement - you can use Visual Studio to configure this just like for the DetailsView control.

Using the code

For anyone used to the GridView, the usage is trivial - just drop and configure. The same design-time editor is used, so the GUI is identical. The only thing to make sure is that the data-source Insert command is configured and the the EditFlag (on the GridView) is turned on. Alternatively, you can use VS to configure the GridView and then just change tags to the InsertableGrid.

The following additional events/properties were added to the InsertableGrid (available through the Designer):

  • bool AllowInsert - Defaults to true. Once this property is cleared, it behaves just like the regular GridView.
  • GridViewUpdatedEventHandler RowInserting - The event is fired right before the row insertion. Fill up the default values here, if needed. Same as RowUpdating (got a little lazy here and didn't implement a new delegate - rather reused the one from the update).
  • GridViewUpdatedEventHandler RowInserted - The event is fired just after the insert happens. Check and clear ExceptionHandled (as needed) here, just like you would with RowUpdating.

Additionally, the RowCreated event will be generated for FooterRow, allowing you to fill up some of the input fields with default values:

C#
protected void InsertableGrid1_RowInserted(object sender, GridViewUpdatedEventArgs e) {
    if (e.Exception != null) {
        Label3.Text = e.Exception.Message;
        e.ExceptionHandled = true;
    }
}

protected  void InsertableGrid1_RowCreated(object  sender, GridViewRowEventArgs e) {
    if (e.Row.RowType == DataControlRowType.Footer 
                      && e.Row.DataItem is DataRowView) { 
        DataRowView r = e.Row.DataItem as DataRowView; 
        r["schStart"] = DateTime.Now.ToShortDateString(); 
        r["schEnd"] = DateTime.Now.AddDays(2).ToShortDateString(); 
    } 
}

Points of interest / Implementation details

In order to implement this functionality, the following tasks need to be accomplished:

  • Make sure that the empty GridView still displays a header row.
  • Optionally, create a new FooterRow and fill it up with the same input elements specified for the Edit mode (EditTemplate).
  • Create and process a new Insert command. Generate the appropriate event handlers.
  • Provide for two-way binding for the footer (insert) row so the data on the insert row can be easily initialized.

Make sure header/footer rows are still created

This proved to be quite a task. GridView insists on creating a single cell table when there is no data. To address this issue, I had to override the protected override int CreateChildControls(IEnumerable dataSource, bool dataBinding) method and check the return code from the base class. If the return code is 0 (among all other), then it means that there is no data in the GridView and I need to go and create a header/footer (insert) row. base.CreateRow is used here to create the rows.

C#
int ret = base.CreateChildControls(dataSource, dataBinding);
if (Columns.Count == 0 || DesignMode || !AllowInsert)
    return ret;
DataControlField[] flds = new DataControlField[Columns.Count];
Columns.CopyTo(flds, 0);
if (ret == 0) {
    Controls.Clear();
    Table t = new Table();
    Controls.Add(t);

    GridViewRow r = CreateRow(-1, -1, DataControlRowType.Header,
          DataControlRowState.Normal);
    this.InitializeRow(r, flds);
    t.Rows.Add(r);

    gvFooterRow = CreateRow(-1, -1, DataControlRowType.Footer,
          DataControlRowState.Insert);
    this.InitializeRow(gvFooterRow, flds);
    t.Rows.Add(gvFooterRow);
}
else
    gvFooterRow = base.FooterRow;

Fill-up footer/insert row with edit elements

I thought it would be quite a chore to have to define all the same templates for the footer row as for the edit rows. That was what most of the solutions to this problem were offering. I thought it would make sense to automatically create a set of input elements on the footer row. So, right after the FooterRow is identified/created, I iterate through all the columns and create the appropriate cells on the footer row.

C#
for (int i =  0;  i <  Columns.Count; i++) {
    DataControlFieldCell cell = (DataControlFieldCell)FooterRow.Cells[i];
    DataControlField fld = Columns[i];
    if (fld is CommandField) {
        CommandField cf = (CommandField)fld;
        CommandField ins = new CommandField();
        ins.ButtonType = cf.ButtonType;
        ins.InsertImageUrl = cf.InsertImageUrl;
        ins.InsertText = cf.InsertText;
        ins.CancelImageUrl = cf.CancelImageUrl;
        ins.CancelText = cf.CancelText;
        ins.InsertVisible = true;
        ins.ShowInsertButton = true;
        ins.Initialize(false, this);
        ins.InitializeCell(cell, DataControlCellType.DataCell,
                 DataControlRowState.Insert, -1);
    }
    else {
        fld.Initialize(base.AllowSorting, this);
        fld.InitializeCell(cell, DataControlCellType.DataCell,
                  DataControlRowState.Edit | DataControlRowState.Insert, -1);
    }
}

Allow for the two-way binding on the insert/footer row

One thing that I think is missing in the new DetailsView data bound control is the ability to nicely initialize the insert data. Over here, I thought it would be nice to correct this error. So, I would create a dummy DataTable and fill it up with the values for each column. Then, I call the OnRowCreated function (raise the event) to allow the application to initialize the insert data (see InsertableGrid1_RowCreated above). That is especially useful when you have a BoundField where you can't easily identify the input controls. Of course, if you have templated columns, then you can use the Row.FindControl() function since you would know the name of the control (just like you would with the DetailsView control).

C#
OrderedDictionary dict = new OrderedDictionary();
base.ExtractRowValues(dict, FooterRow, true, true);
DataTable tbl = new DataTable();
DataRow row = tbl.Rows.Add();
foreach (string k in dict.Keys) {
    tbl.Columns.Add(new DataColumn(k));
    row[k] = dict[k];
}
FooterRow.DataItem = new DataView(tbl)[0];
GridViewRowEventArgs args1 = new GridViewRowEventArgs(FooterRow);
this.OnRowCreated(args1);
FooterRow.DataBind();
this.OnRowDataBound(args1);
FooterRow.DataItem = null;
foreach (DataControlField f in Columns)
    f.Initialize(this.AllowSorting, this);

Outstanding issues

  • Can't put my finger on it, but somehow, during the design, ItemTemplate/EditTemplate comes out in lower case.
  • Would like to change the designer to draw the grid with an insert line in it to provide for visual cue.
  • The sample ASPX page works with the database on my local machine. You would need to either create the table or change the page. Once again, the configuration is identical to the GridView, so either drop and configure, or configure the GridView and then just change tags.

History

  • Apply footer styles to insert row - Changes made to set ShowFooter flags as long as AllowInsert is set. This forces the GridView to apply FooterStyle to the insert row.
  • Allow page validation to cancel insert - Added check for Page.IsValid to the OnRowCommand. Avoid insertion if failure.
  • Fixed crash with auto-increment columns - Fixed the initialization for the footer row binding to include auto-increment columns.
  • Changed the RowInserting event to GridViewUpdateEventHandler type - To prevent crash and to be more consistent. Note: this may affect compatibility with the prior version.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
http://www.GaspMobileGames.com
United States United States
Writing code since 1987 using whatever language/environment you can imagine. Recently got into the mobile games. Feel free to check them out at http://www.GaspMobileGames.com

Comments and Discussions

 
AnswerRe: validation group Pin
shuameston24-Mar-07 17:29
shuameston24-Mar-07 17:29 
GeneralRe: validation group Pin
Mark Henke16-Aug-07 4:28
Mark Henke16-Aug-07 4:28 
GeneralRe: validation group Pin
kiboumz29-Feb-08 3:12
kiboumz29-Feb-08 3:12 
GeneralRe: validation group Pin
Settled12-Jul-08 3:20
Settled12-Jul-08 3:20 
Questionupdate delete and insert data in the table in datagrid Pin
praveen15088222-Mar-07 9:06
praveen15088222-Mar-07 9:06 
GeneralInsert problem Pin
svingal12-Mar-07 21:39
svingal12-Mar-07 21:39 
GeneralRe: Insert problem Pin
Realgar12-Apr-07 7:58
Realgar12-Apr-07 7:58 
GeneralUpdatePanel Pin
DarnocRekrap9-Mar-07 2:47
DarnocRekrap9-Mar-07 2:47 
Great tool. Thanks for sharing it.

I have a problem however whilst using it in an AJAX Update panel.
Only when you have no records to start with it still does a full postback.

Any ideas?

Conrad
QuestionRe: UpdatePanel Pin
vlpk28-Nov-07 3:58
vlpk28-Nov-07 3:58 
Generalthe "Insert" command in template Pin
ernest_elias9-Mar-07 0:05
ernest_elias9-Mar-07 0:05 
QuestionHow to modify the Insertable Gridview Pin
stan_da_man7-Mar-07 3:43
stan_da_man7-Mar-07 3:43 
GeneralMicrosoft.Web.Extensions Pin
ernest_elias6-Mar-07 5:03
ernest_elias6-Mar-07 5:03 
GeneralRe: Microsoft.Web.Extensions Pin
gstolarov6-Mar-07 5:13
gstolarov6-Mar-07 5:13 
GeneralRe: Microsoft.Web.Extensions Pin
ernest_elias6-Mar-07 5:43
ernest_elias6-Mar-07 5:43 
GeneralCatching exceptions differ from original GridView Pin
AndersJuulsFirma6-Feb-07 20:35
AndersJuulsFirma6-Feb-07 20:35 
QuestionInsert before/after Pin
Graham Barlow5-Feb-07 23:16
professionalGraham Barlow5-Feb-07 23:16 
GeneralCannot apply skin... Pin
JuanPieterse31-Jan-07 20:55
JuanPieterse31-Jan-07 20:55 
GeneralRe: Cannot apply skin... Pin
vlpk5-Nov-08 11:36
vlpk5-Nov-08 11:36 
GeneralInsert/Cancel shown twice Pin
AndersJuulsFirma24-Jan-07 23:25
AndersJuulsFirma24-Jan-07 23:25 
AnswerRe: Insert/Cancel shown twice Pin
syrok2223-Apr-07 6:17
syrok2223-Apr-07 6:17 
GeneralAutoGenerateEditButton (the column in which the first insert field is displayed) Pin
AndersJuulsFirma24-Jan-07 22:45
AndersJuulsFirma24-Jan-07 22:45 
QuestionBound DropDown in Edit Template Pin
rhoffman30322-Jan-07 13:00
rhoffman30322-Jan-07 13:00 
AnswerRe: Bound DropDown in Edit Template Pin
gstolarov23-Jan-07 4:37
gstolarov23-Jan-07 4:37 
GeneralRe: Bound DropDown in Edit Template Pin
rhoffman30323-Jan-07 9:27
rhoffman30323-Jan-07 9:27 
GeneralRe: Bound DropDown in Edit Template Pin
rhoffman30323-Jan-07 9:59
rhoffman30323-Jan-07 9:59 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.