Click here to Skip to main content
Click here to Skip to main content

GridView with insert line

By , 1 Jun 2007
Rate this:
Please Sign up or sign in to vote.

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:

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.

    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.

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).

    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)

About the Author

gstolarov
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

 
QuestionCalling the Insert Method PinmemberMark Iovino11-Nov-12 15:18 
AnswerRe: Calling the Insert Method Pinmembergstolarov11-Nov-12 16:51 
GeneralRe: Calling the Insert Method PinmemberMark Iovino11-Nov-12 18:24 
QuestionMy vote of 5 PinmemberRichard Blythe15-Mar-12 11:28 
AnswerRe: My vote of 5 Pinmembergstolarov15-Mar-12 11:46 
Questionframework 4 error PinmemberMember 82795213-Jan-12 18:21 
I used this great control for years, but now with framework 4 i have some problems with insert event. The specific error is that after insert a record in gridview is launched event of container form. Tis behavior is only in framework 4
Any Ideas?
Thanks
GeneralToggling insert mode in code Pinmemberboxersoft16-Aug-09 9:34 
GeneralRe: Toggling insert mode in code Pinmembergstolarov17-Aug-09 4:07 
GeneralRe: Toggling insert mode in code Pinmemberboxersoft17-Aug-09 6:55 
GeneralProblem using CalendarExtender PinmemberYuliyan26-Jan-09 23:44 
GeneralVB Version Code [modified] Pinmembermalbert6921-Oct-08 10:12 
GeneralProblem with AutoGenerated buttons (solution) Pinmembertjastrzebski21-Apr-08 7:01 
GeneralBlank field values after handled exception Pinmemberddddddaaa2-Apr-08 5:16 
GeneralRe: Blank field values after handled exception Pinmembergstolarov8-Nov-08 14:40 
AnswerDropDownList invalid SelectedValue fix (kindof) PinmemberJethro Hoobershtanker14-Feb-08 5:56 
GeneralRe: DropDownList invalid SelectedValue fix (kindof) PinmemberFelipe Teixeira18-Aug-08 3:28 
GeneralDropdown + EditItemTemplate bug = REAL FIX IN HERE PinmemberFelipe Teixeira18-Aug-08 4:32 
GeneralRe: DropDownList invalid SelectedValue fix (kindof) Pinmembergstolarov18-Aug-08 10:47 
Questiondifferent between gridview used datasource(wizard) and the one used dataset? PinmemberSpring7714-Jan-08 21:28 
GeneralCannot be used as a drop-in replacement for asp:GridView PinmemberPerry29-Dec-07 2:19 
QuestionSkinnable? PinmemberAmy de Buitlir26-Nov-07 22:35 
Generalinsert into DataTable using ObjectDataSource Pinmembermegadith14-Nov-07 4:48 
AnswerA functional InsertVisible [modified] PinmemberChrisRico11-Oct-07 11:29 
QuestionCan I use a FooterTemplate? Pinmembervlpk31-Jul-07 11:01 
QuestionNo comments? Pinmemberawarberg30-Jun-07 3:28 

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

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

| Advertise | Privacy | Mobile
Web01 | 2.8.140415.2 | Last Updated 1 Jun 2007
Article Copyright 2006 by gstolarov
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid