Always show FooterTemplate, even no data
Asked Answered
E

3

8

Is there a short way to make a FooterTemplate (in a GridView) always visible, even when DataSource is empty?

Export answered 15/6, 2009 at 7:39 Comment(2)
Why you want to acheive this?Vandavandal
Please take a look at what i commented to below, I explained what I need it for.Export
T
5

If you want it to always display, regardless of content, can't you just put the footer html outside the GridView, instead of in the FooterTemplate?

If that's not an option for some reason, then you can either add an null row to your data source if it's empty, or subclass the GridView & override the default behaviour.

Those are the only options I'm aware of (although its been a while since the last time I used a GridView).

Teaser answered 15/6, 2009 at 7:48 Comment(3)
I don't really care doing it with with Html, the problem is I want the columns to fit the width of the GridView columns. I want it to show some summarization when data exist, and a insert item (which i implemented in the footer, know what i mean?) when button "New" is pressed on the item template, or show the footer always. in other words: *is there a way to evoke showing the footer (when no data)? *what is actually this null data row thing, didn't getcha (im using EntityDataSource, i think will be more complicated or impossible at all). Thanks buddy.Export
I don't want to use an empty row, I don't mind subclassing the GridView but no dummy data. 've u got somtn'?Export
The 2nd link I included (mattberseth.com/blog/2007/07/…) has some example code to allow you to have a grid with a ShowFooterWhenEmpty property.Teaser
W
7

I was having trouble with this as well. The link from Alconja helps a lot (Thanks Alconja) but GridView.FooterRow then returns null. I need it for inserting new records from the footer.

This is my final solution that works. Now you can insert data from the footer even if the grid is empty.

GridViewExtended.cs (a class in the App_Code folder):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace YourNamespace
{

  public class GridViewExtended : GridView
  {
    #region Public Properties
    [Category("Behavior")]
    [Themeable(true)]
    [Bindable(BindableSupport.No)]
    public bool ShowFooterWhenEmpty
    {
      get
      {
        if (this.ViewState["ShowFooterWhenEmpty"] == null)
        {
          this.ViewState["ShowFooterWhenEmpty"] = false;
        }

        return (bool)this.ViewState["ShowFooterWhenEmpty"];
      }
      set
      {
        this.ViewState["ShowFooterWhenEmpty"] = value;
      }
    }
    #endregion

    private GridViewRow _footerRow2;
    public override GridViewRow FooterRow
    {
      get
      {
        GridViewRow f = base.FooterRow;
        if (f != null)
          return f;
        else
          return _footerRow2;
      }
    }

    protected override int CreateChildControls(System.Collections.IEnumerable dataSource, bool dataBinding)
    {
      int rows = base.CreateChildControls(dataSource, dataBinding);

      //  no data rows created, create empty table if enabled
      if (rows == 0 && (this.ShowFooterWhenEmpty))
      {
        //  create the table
        Table table = this.CreateChildTable();

        DataControlField[] fields;
        if (this.AutoGenerateColumns)
        {
          PagedDataSource source = new PagedDataSource();
          source.DataSource = dataSource;

          System.Collections.ICollection autoGeneratedColumns = this.CreateColumns(source, true);
          fields = new DataControlField[autoGeneratedColumns.Count];
          autoGeneratedColumns.CopyTo(fields, 0);
        }
        else
        {
          fields = new DataControlField[this.Columns.Count];
          this.Columns.CopyTo(fields, 0);
        }

        if (this.ShowHeaderWhenEmpty)
        {
          //  create a new header row
          GridViewRow headerRow = base.CreateRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal);
          this.InitializeRow(headerRow, fields);

          //  add the header row to the table
          table.Rows.Add(headerRow);
        }

        //  create the empty row
        GridViewRow emptyRow = new GridViewRow(-1, -1, DataControlRowType.EmptyDataRow, DataControlRowState.Normal);
        TableCell cell = new TableCell();
        cell.ColumnSpan = fields.Length;
        cell.Width = Unit.Percentage(100);

        //  respect the precedence order if both EmptyDataTemplate
        //  and EmptyDataText are both supplied ...
        if (this.EmptyDataTemplate != null)
        {
          this.EmptyDataTemplate.InstantiateIn(cell);
        }
        else if (!string.IsNullOrEmpty(this.EmptyDataText))
        {
          cell.Controls.Add(new LiteralControl(EmptyDataText));
        }

        emptyRow.Cells.Add(cell);
        table.Rows.Add(emptyRow);

        if (this.ShowFooterWhenEmpty)
        {
          //  create footer row
          _footerRow2 = base.CreateRow(-1, -1, DataControlRowType.Footer, DataControlRowState.Normal);
          this.InitializeRow(_footerRow2, fields);

          //  add the footer to the table
          table.Rows.Add(_footerRow2);
        }

        this.Controls.Clear();
        this.Controls.Add(table);
      }

      return rows;
    }
  }

}

In the aspx page, simply add

<%@ Register TagPrefix="YourPrefix" Namespace="YourNamespace" %>

and replace <asp:GridView with <YourPrefix:GridViewExtended

Hope it helps someone.

Whitworth answered 5/6, 2012 at 4:50 Comment(3)
I tried this because I had a gridview with a footer with the option of adding a new record. Users would have to click on an "Add New" button in the footer after which they would see controls to add a new row. This code does not work as expected (You would probably have to replace the call to base.CreateChildControls with code and set the id's etc).Whitehouse
The problem for me with this solution is that the RowDataBound event does not fire for the footer for some reason when the grid is empty. Since I need to populate some dropdowns there, this is a fatal flaw.Isogamy
ShowFooterWhenEmpty="True"Julesjuley
T
5

If you want it to always display, regardless of content, can't you just put the footer html outside the GridView, instead of in the FooterTemplate?

If that's not an option for some reason, then you can either add an null row to your data source if it's empty, or subclass the GridView & override the default behaviour.

Those are the only options I'm aware of (although its been a while since the last time I used a GridView).

Teaser answered 15/6, 2009 at 7:48 Comment(3)
I don't really care doing it with with Html, the problem is I want the columns to fit the width of the GridView columns. I want it to show some summarization when data exist, and a insert item (which i implemented in the footer, know what i mean?) when button "New" is pressed on the item template, or show the footer always. in other words: *is there a way to evoke showing the footer (when no data)? *what is actually this null data row thing, didn't getcha (im using EntityDataSource, i think will be more complicated or impossible at all). Thanks buddy.Export
I don't want to use an empty row, I don't mind subclassing the GridView but no dummy data. 've u got somtn'?Export
The 2nd link I included (mattberseth.com/blog/2007/07/…) has some example code to allow you to have a grid with a ShowFooterWhenEmpty property.Teaser
Y
3

As one of the previous commenters mentioned, the RowDataBound event doesn't fire for the footer. I found another code snippet that addresses this issue, but in addition to displaying the footer, it explicitly creates the row (firing the RowCreated event) and binds it (firing the RowDataBound event).

I've converted the above referenced code to c# using a code converter and made a few minor tweaks. I also included the comments I made as I stepped through the code to break it down. The RowCreated and RowDataBound events are firing now and I'm able to populate dropdowns in footers.

    using System.Linq;
    using System.Web.UI.WebControls;
    using System.ComponentModel;

    namespace WebUI.Controls
    {
        //modified from https://mcmap.net/q/896856/-show-gridview-footer-on-empty-grid
        public class GridViewExtended : GridView
        {

            private GridViewRow _footerRow;
            [DefaultValue(false), Category("Appearance"), Description("Include the footer when the table is empty")]
            public bool ShowFooterWhenEmpty { get; set; }

            [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Browsable(false)]
            public override GridViewRow FooterRow {
                get {
                    if ((this._footerRow == null)) {
                        this.EnsureChildControls();
                    }
                    return this._footerRow;
                }
            }

            protected override int CreateChildControls(System.Collections.IEnumerable dataSource, bool dataBinding)
            {
                //creates all the rows that would normally be created when instantiating the grid
                int returnVal = base.CreateChildControls(dataSource, dataBinding);
                //if no rows were created (i.e. returnVal == 0), and we need to show the footer row, then we need to create and bind the footer row.
                if (returnVal == 0 && this.ShowFooterWhenEmpty) {
                    Table table = this.Controls.OfType<Table>().First<Table>();
                    DataControlField[] dcf = new DataControlField[this.Columns.Count];
                    this.Columns.CopyTo(dcf, 0);
                    //creates the footer row
                    this._footerRow = this.CreateRow(-1, -1, DataControlRowType.Footer, DataControlRowState.Normal, dataBinding, null, dcf, table.Rows, null);
                    if (!this.ShowFooter) {
                        _footerRow.Visible = false;
                    }
                }
                return returnVal;
            }

            private GridViewRow CreateRow(int rowIndex, int dataSourceIndex, DataControlRowType rowType, DataControlRowState rowState, bool dataBind, object dataItem, DataControlField[] fields, TableRowCollection rows, PagedDataSource pagedDataSource)
            {
                GridViewRow row = this.CreateRow(rowIndex, dataSourceIndex, rowType, rowState);
                GridViewRowEventArgs e = new GridViewRowEventArgs(row);
                if ((rowType != DataControlRowType.Pager)) {
                    this.InitializeRow(row, fields);
                } else {
                    this.InitializePager(row, fields.Length, pagedDataSource);
                }
                //if the row has data, sets the data item
                if (dataBind) {
                    row.DataItem = dataItem;
                }
                //Raises the RowCreated event
                this.OnRowCreated(e);
                //adds the row to the gridview's row collection
                rows.Add(row);
                //explicitly binds the data item to the row, including the footer row and raises the RowDataBound event.
                if (dataBind) {
                    row.DataBind();
                    this.OnRowDataBound(e);
                    row.DataItem = null;
                }
                return row;
            }

        }

    }
Yoruba answered 4/6, 2014 at 13:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.