Always show FooterTemplate, even no data

后端 未结 3 1497
太阳男子
太阳男子 2020-12-16 22:24

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

相关标签:
3条回答
  • 2020-12-16 22:41

    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://stackoverflow.com/questions/3437581/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;
                }
    
            }
    
        }
    
    0 讨论(0)
  • 2020-12-16 22:52

    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.

    0 讨论(0)
  • 2020-12-16 22:54

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

    0 讨论(0)
提交回复
热议问题