Beanie posted on May 26, 2009 20:46

Sometimes it would be nice if things did what you expect them to do, for example the gridview in .NET. I expected it to display the header and footer rows even if the query returned no rows, als this is not the case, there isn't even a switch to turn it on. After alot of searching I found several solutions, but struggled to make them work, finally I did and I thought I would share how it's done.

First of all we need to create a class - showheader.cs this goes in the App_Code folder.

GridViewAlwaysShow.cs

   1:  using System;
   2:  using System.Collections;
   3:  using System.Data;
   4:  using System.Web.UI.WebControls;
   5:   
   6:  namespace AlwaysShowHeaderFooter 
   7:  {
   8:      public delegate IEnumerable MustAddARowHandler(IEnumerable data);
   9:      public class GridViewAlwaysShow : GridView 
  10:      {
  11:          //Flag used to identify if the datasource is empty.
  12:          bool _isEmpty = false;
  13:          protected override void OnDataBound(EventArgs e) 
  14:          {
  15:              //if in DesignMode, don't do anything special. Just call base and return.
  16:              if (DesignMode) 
  17:              {
  18:                  base.OnDataBound(e);
  19:                  return;
  20:              }
  21:              //hide the dummy row.
  22:              if (_isEmpty) 
  23:              {
  24:                  Rows[0].Visible = false;
  25:              }
  26:              base.OnDataBound(e);
  27:          }
  28:          protected override void PerformDataBinding(IEnumerable data) 
  29:          {
  30:              //If in DesignMode, don't do anything special. Just call base and return.
  31:              if (DesignMode) 
  32:              {
  33:                  base.PerformDataBinding(data);
  34:                  return;
  35:              }            
  36:              //Count the data items.(I wish I knew a better way to do this.)
  37:              int objectItemCount = 0;
  38:              foreach (object o in data) 
  39:              {
  40:                  objectItemCount++;
  41:              }
  42:              //If there is a count, don't do anything special. Just call base and return.
  43:              if (objectItemCount > 0) {
  44:                  base.PerformDataBinding(data);
  45:                  return;
  46:              }            
  47:              //Set these values so the GridView knows what's up.
  48:              SelectArguments.TotalRowCount++;
  49:              _isEmpty = true;
  50:              //If it's a DataView, it will work without having to handle the MustAddARow event.
  51:              if (data.GetType() == typeof(DataView)) 
  52:              {
  53:                  //Add a row and use that new view.
  54:                  DataView dv = (DataView)data;
  55:                  dv.Table.Rows.InsertAt(dv.Table.NewRow(), 0);
  56:                  base.PerformDataBinding(dv.Table.DefaultView);
  57:                  return;
  58:              }
  59:              else 
  60:              {
  61:                  //If you are using some custom object, you need to handle this event.
  62:                  base.PerformDataBinding(OnMustAddARow(data));
  63:                  return;
  64:              }
  65:          }
  66:          protected IEnumerable OnMustAddARow(IEnumerable data) {
  67:              if (MustAddARow == null) {
  68:                  throw new NullReferenceException("The datasource has no rows. You must handle the \"MustAddARow\" Event.");
  69:              }
  70:              return MustAddARow(data);
  71:          }
  72:          public event MustAddARowHandler MustAddARow;
  73:      }
  74:  }

Also we need a class to create the blank row this does nothing (it was this that confused me for quite a while I thought I needed to populate this with something related to my datasource)

Class1.cs

   1:  using System;
   2:   
   3:  public class Class1
   4:  {
   5:      public Class1()
   6:      {                
   7:      }
   8:  }

Then we need to register this in the web.config file

web.config

<pages>
<controls>             
<add tagPrefix="custom"  namespace="AlwaysShowHeaderFooter" />               
</controls>
</pages> 

Finally we need to impliment the table the .aspx pag, this is the same as you would do for a normal gridview, just replace <asp:GridView with <Custom:GridViewAlwaysShow and it will pick up the new namespace.

emptygridview.aspx

<Custom:GridViewAlwaysShow ID="gvGridView" runat="server"
AllowPaging="True"
AllowSorting="True"
AutoGenerateColumns="False"
EmptyDataText="There are no data records to display."
ShowFooter="True"
DataKeyNames="DataField2"
DataSourceID="dsSQL"   OnMustAddARow="gv_MustAddARow">
<Columns>
<asp:BoundField DataField="DataField1" HeaderText="Data Field 1"
SortExpression="DataField1" />
<asp:BoundField DataField="DataField2" HeaderText="Data Field 2"
SortExpression="DataField2" InsertVisible="False" ReadOnly="True" />
<asp:BoundField DataField="DataField3"
HeaderText="Data Field 3"
SortExpression="DataField3" />
</Columns>
</Custom:GridViewAlwaysShow>
<asp:SqlDataSource ID="dsSQL" runat="server"
ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
SelectCommand="selectData" SelectCommandType="StoredProcedure">
<SelectParameters>
<asp:Parameter DefaultValue="0" Name="SearchField" Type="Int32" />
</SelectParameters>
</asp:SqlDataSource> 

And the aspx.cs handleryou will need

using System.Collections.Generic;
using System.Collections;

in addition to any others.

emptygridview.aspx.cs

   1:  protected IEnumerable gv_MustAddARow(IEnumerable data)
   2:      {
   3:          List<Class1> dds = null;
   4:          dds.Add(new Class1());
   5:          return dds;
   6:      } 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Comments

Page List

Search Blog

Tag Cloud

Recent Comments

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2012 Beanie