PAGES

28

Feb 06

Displaying GridView When No Data Exists



One thing thats midly annoying to me about the new gridview control is that it doesn’t display the header row when there is no data. I would like to just have the header displayed like the original table with a single row saying something like “No records found”. The grid has a property for emptydata text which doesn’t look that great in my opinion. I have seen some people use the property to create a new table in there which isn’t the cleanest solution. One way to get the gridview to display how you want is to create a custom control that inherts from gidview. Then you can override the CreateChildControls method to create a the gridview with the all the headers and a blank row with one cell and a text message. Here’s how to do it:


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

public class EmptyGridView : GridView
{
#region Properties

/// <summary>
/// Enable or Disable generating an empty table if no data rows in source
///
</summary>
[
Description("Enable or disable generating an empty table with headers if no data rows in source"),
Category("Misc"),
DefaultValue("true"),
]
public bool ShowEmptyTable
{
get
{
object o = ViewState["ShowEmptyTable"];
return (o != null ? (bool)o : true);
}
set
{
ViewState["ShowEmptyTable"] = value;
}
}

///
<summary>
/// Get or Set Text to display in empty data row
///
</summary>
[
Description("Text to display in empty data row"),
Category("Misc"),
DefaultValue(""),
]
public string EmptyTableRowText
{
get
{
object o = ViewState["EmptyTableRowText"];
return (o != null ? o.ToString() : “”);
}
set
{
ViewState["EmptyTableRowText"] = value;
}
}

#endregion


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

//no data rows created, create empty table if enabled
if (numRows == 0 && ShowEmptyTable)
{
//create table
Table table = new Table();
table.ID = this.ID;

//create a new header row
GridViewRow row = base.CreateRow(-1, -1, DataControlRowType.Header,DataControlRowState.Normal);

//convert the exisiting columns into an array and initialize
DataControlField[] fields = new DataControlField[this.Columns.Count];
this.Columns.CopyTo(fields,0);
this.InitializeRow(row, fields);
table.Rows.Add(row);

//create the empty row
row = new GridViewRow(-1, -1, DataControlRowType.DataRow, DataControlRowState.Normal);
TableCell cell = new TableCell();
cell.ColumnSpan = this.Columns.Count;
cell.Width = Unit.Percentage(100);
cell.Controls.Add(new LiteralControl(EmptyTableRowText));
row.Cells.Add(cell);
table.Rows.Add(row);

this.Controls.Add(table);
}

return numRows;
}
}

You can download the code here. Reflector was helpful in seeing how grids were created in the framework as was Fredrik Normen’s blog which always has great asp.net info. Everytime i search for asp.net problem, its usually covered on his site.

31 comments , permalink


  • http://

    Thanks for posting this. It was exactly what I was looking for. One minor tweak:
    table.CssClass = this.CssClass;

  • http://

    hi marshall,
    I got error : CreateChildControls(System.Collections.IEnumerable, bool)”: no suitable method found to override.

    how i ll solve this?

  • Kevin Marshall

    Dinu,

    Could you be a little more specific? Are you inheriting from GridView?

  • http://

    How Do I connect the above code to my gridview

    Thanks

  • http://

    Hi
    I am fairly new to ASP.Net and I would appreciate your help

    I have a gridview in which I am inserting records in the footer. I would like to display the gridview when the gridview is empty so that I can insert my data. I am using the first code above. The one that inherits from a gridview i.e public class EmptyGridView : GridView. How do I call this class so that it works with the gridview I already have

    Thanks

  • http://

    Make sure that your class “EmptyGridView” got the namespace namespace EmptyGridView.

    Register the class above the aspx page like < %@ Register TagPrefix="Custom" Namespace="EmptyGridView" %>

    Call control:



    I like this solution, it”s easy and workable

  • http://

    Great solution, Thank you!

  • http://

    i bein in asp.net and i cannot insert the custom control
    i created the EmptyGridView class in the EmptyGridView namespace,
    added the Register tag just below the page tag
    and adding the control like this

    the designer say to me that the tag is unknown, i can compil but on runtime, i have errror, tagt unknown

    i did something wrong ?

  • http://

    This looks promising, but I get the same as Olivier.

  • http://

    Brilliant! I”d already created a custom control so just popped the CreateChildControls override in and it worked a treat!

  • http://

    Couple of notes

    if using .net 3.5
    move the register < %@ Register TagPrefix="Custom" Namespace="EmptyGridView" %>
    entry to the web.config under controls as

    i also added changed it slightly adding

    row = base.CreateRow(-1, -1, DataControlRowType.Footer, DataControlRowState.Normal);
    this.InitializeRow(row, fields);
    table.Rows.Add(row);
    OnRowDataBound(new GridViewRowEventArgs(row));

    as the second row and the below so that it waorks as a footerrow again for adding on an empty grid.

    public override GridViewRow FooterRow
    {
    get
    {
    if (!ShowEmptyTable)
    return base.FooterRow;
    else
    return ((Table)this.Controls[0]).Rows[1] as GridViewRow;
    }
    }

    hope it helps

  • http://

    I need a vb.net code to make an empty row

  • http://

    Great work, thank you. Unfortunately the control doesn”t return FooterRow, so I can”t use FindControl to get values. Has anyone found a fix for that?

  • http://

    hi all

    when i build the sample , i get this error
    Missing partial modifier on declaration of type ”EmptyGridView ”; another partial declaration of this type exists

  • http://

    If you want use footer for inserting data:

    if (this.ShowFooterWhenEmpty)
    {
    // create footer row
    GridViewRow footerRow = base.CreateRow(-1, -1, DataControlRowType.Footer, DataControlRowState.Normal);
    _footerRow = base.CreateRow(-1, -1, DataControlRowType.Footer, DataControlRowState.Edit);

    this.InitializeRow(_footerRow, fields);

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

    _footerRow.DataBind();

    }

  • http://

    Hi –

    I”m getting Property access must assign to the property or use it value. any thought?

  • http://

    I have textboxes in my header columns and they become null references with this fix, anyone with more brains ready to offer up a solution? -.-)

  • http://

    Thanks a lot !

    There is a difference beetwen the normal gridview and the replacement table : the ClientId is different.

    I changed and added a few line of code to make the created table return the expected ClientId and also render it.

    In CreateChildControls, change :
    //create table
    Table table = new Table();
    table.ID = this.ID;
    by
    //create table
    GvwEmptyTable table = new GvwEmptyTable();
    table.ID = this.ID;
    table.ClientIdOverride = this.ClientID;

    Add right before the end of the class :
    ///

    /// Summary description for RnoGvwEmptyTable
    ///

    private class GvwEmptyTable : System.Web.UI.WebControls.Table
    {
    ///

    /// ClientId Override, needed for empty GridView in order to get the same ClientId
    ///

    public string ClientIdOverride;

    ///

    /// Client Id Override
    ///

    public override string ClientID
    {
    get
    {
    return ClientIdOverride.Nvl(base.ClientID);
    }
    }
    }

  • http://

    Denis.. whatz ClientIdOverride.”Nvl” ??

  • http://

    Excellent piece of code, solved the problem we had where we had filters in the header, so a user could filter out all results and then not be able to change them!

    Thanks!

  • http://

    Sorry Guys New to ASP

    Can you let me know how to call the class to show the empty grid.

    Thank

    M

  • http://

    If you happen to have filter controls that has to be bound like me, call ”OnRowDataBound” event after adding a header row:

    //create a new header row
    GridViewRow row = base.CreateRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal);

    //convert the exisiting columns into an array and initialize
    DataControlField[] fields = new DataControlField[this.Columns.Count];
    this.Columns.CopyTo(fields, 0);
    this.InitializeRow(row, fields);
    table.Rows.Add(row);

    OnRowDataBound(new GridViewRowEventArgs(row)); // ** This should invoke gvMine_RowDataBound(o, e) event!

    Thanks heaps!

  • club penguin cheats

    Unfortunately the control doesn”t return FooterRow, so I can”t use FindControl to get values. Has anyone found a fix for that?

  • http://

    VB Code for that same,
    it will work
    Imports System
    Imports Microsoft.VisualBasic
    Imports System.Collections.Generic
    Imports System.ComponentModel
    Imports System.Text
    Imports System.Web.UI
    Imports System.Web.UI.WebControls
    Public Class EmptyGridView
    Inherits GridView

    Public Property ShowEmptTable() As Boolean
    Get
    Dim o As Object = ViewState(“ShowEmptyTable”)
    Return IIf(o <> “”, CBool(o), True)
    End Get
    Set(ByVal value As Boolean)
    ViewState(“ShowEmptyTable”) = value
    End Set
    End Property

    Public Property EmptyTableRowText() As String
    Get
    Dim o As Object = ViewState(“ShowEmptyTable”)
    Return IIf(o <> “”, o.ToString, “”)
    End Get
    Set(ByVal value As String)
    ViewState(“ShowEmptyTable”) = value
    End Set
    End Property

    Protected Overrides Function CreateChildControls(ByVal dataSource As System.Collections.IEnumerable, ByVal dataBinding As Boolean) As Integer
    Dim numRows As Integer = MyBase.CreateChildControls(dataSource, dataBinding)
    If numRows = 0 And ShowEmptTable Then
    Dim table As New Table
    Dim row As GridViewRow = MyBase.CreateRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal)
    Dim fields(Columns.Count) As DataControlField
    Columns.CopyTo(fields, 0)
    InitializeRow(row, fields)
    table.Rows.Add(row)

    row = New GridViewRow(-1, -1, DataControlRowType.DataRow, DataControlRowState.Normal)
    Dim cell As New TableCell
    cell.ColumnSpan = Columns.Count
    cell.Width = Unit.Percentage(100)
    cell.Controls.Add(New LiteralControl(EmptyTableRowText))
    row.Cells.Add(cell)
    table.Rows.Add(row)
    Controls.Add(table)
    End If

    Return numRows
    End Function

    End Class

  • http://

    can u plz help its show error that custom tag he not available

  • http://

    @Ghayas tanks to the vb code you given. that help a lot :)

    i have go through the solution gived by Menno,but the same error come out that cant found the custom tags.

    who can help with this question?

  • http://

    Thanks to Kevin Marshall for pointing us in the right direction. The converted VB function posted above is junk and the main authors C# function can throw NullReferenceException because of the – InitializeRow(row, fields) – statement when there are any null columns in the fields array. Below is a working version of the main pages method converted to VB:

    Imports System
    Imports System.Web.UI
    Imports System.Web.UI.WebControls

    Public Class EmptyGridView
    Inherits GridView

    ”””

    ””” Enable or Disable generating an empty table if no data rows in source
    ”””

    Public Property ShowEmptyTable() As Boolean
    Get
    Dim o As Object = ViewState(“ShowEmptyTable”)
    Return IIf(o Is Nothing, True, CBool(o))
    End Get
    Set(ByVal value As Boolean)
    ViewState(“ShowEmptyTable”) = value
    End Set
    End Property

    ”””

    ””” Get or Set Text to display in empty data row
    ”””

    Public Property EmptyTableRowText() As String
    Get
    Dim o As Object = ViewState(“EmptyTableRowText”)
    ”Return IIf(o Is Nothing, “”, o.ToString()) ”throws null reference exception because VB rocks
    If o Is Nothing Then
    Return “”
    Else
    Return o.ToString()
    End If
    End Get
    Set(ByVal value As String)
    ViewState(“EmptyTableRowText”) = value
    End Set
    End Property

    Protected Overrides Function CreateChildControls(ByVal dataSource As System.Collections.IEnumerable, ByVal dataBinding As Boolean) As Integer
    Dim numRows As Integer = MyBase.CreateChildControls(dataSource, dataBinding)
    If numRows = 0 And ShowEmptyTable Then
    Dim table As New Table
    table.ID = Me.ID

    Dim row As GridViewRow = MyBase.CreateRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal)

    Dim fields(Me.Columns.Count) As DataControlField
    MyBase.Columns.CopyTo(fields, 0)
    Dim noNullsFields() As DataControlField = RemoveNullsFromDataControlField(fields)
    MyBase.InitializeRow(row, noNullsFields)

    table.Rows.Add(row)

    row = New GridViewRow(-1, -1, DataControlRowType.DataRow, DataControlRowState.Normal)
    Dim cell As New TableCell
    cell.ColumnSpan = Me.Columns.Count
    cell.Width = Unit.Percentage(100)
    cell.Controls.Add(New LiteralControl(EmptyTableRowText))
    row.Cells.Add(cell)
    table.Rows.Add(row)

    Me.Controls.Add(table)
    End If
    Return numRows
    End Function

    Private Function RemoveNullsFromDataControlField(ByVal fields() As DataControlField) As DataControlField()
    Dim numFields As Integer

    For Each field As DataControlField In fields
    If Not field Is Nothing Then
    numFields = numFields + 1
    End If
    Next

    numFields = numFields – 1

    Dim noNullsFields(numFields) As DataControlField
    Dim i As Integer
    For i = 0 To numFields
    noNullsFields(i) = fields(i)
    Next

    Return noNullsFields
    End Function

    End Class

  • http://

    Hey, anyone who is having problems with the custom tag:

    Just add to the page i.e

    < %@ Register TagPrefix="GVV" Namespace="GridViewVacio" %>

    Now, if you read carefully the line, it says TagPrefix and “NameSpace”, and in the example there isn”t a namespace, just a class, so add a namespace:

    namespace GridViewVacio
    {
    public class EmptyGridView : GridView
    {
    //all the code
    }
    }

    Now, you can call the code (in my example) as: “GVV:GridViewVacio”


    blablablabla

    Greetings

  • http://

    Forget my last post, this is the real-deal:

    STEP 1:

    Create an empty class with its namespace in your project, i.e. in APP_CODE

    namespace GridViewVacio
    {
    public class GridViewVacio : GridView
    {
    }
    }

    STEP 2:

    Paste into this code:

    http://mattberseth.com/blog/2007/07/how_to_show_header_and_footer.html

    STEP 3:

    Add the prefix to your aspx:

    < %@ Register Namespace="GridViewVacio" TagPrefix="GVV" %>

    STEP 4:

    Modify your Gridview prefix (GVV:GridviewVacio):




    STEP 5:

    Add the attributes ” to your GridView




    STEP: 6

    Databind your Gridview in your page load no matter if it hasn”t anything binded.

    protected void Page_Load(object sender, EventArgs e)
    {
    if(!IsPostBack)
    this.MyGridView.DataBind();
    }

    STEP 7:

    ENJOY

  • http://

    hi.
    I have gone through above code.. I have one doubt.. I have already Gridview name (CompanyGrd” in my from which is bound to some tables. Now if there is no record in dataset i just want to display columns of my gridview. I tried a lot but not able to find the solution to use ur code with my existing gridview.

    Thanks a lot
    GKP

  • thomas sabo bee charm

    Many style freaks really feel the fact that existence and sustenance of makes like Moncler have kept them pepped up. a few of individuals persons who go mad anytime there is generally a refreshing launch from Moncler, really feel only this kind of makes can remind them that real style can by no means pass away out. It appears the manufacturer has converted a large quantity of persons into style freaks having a using up wish for fashion, new styles and distinct designs altogether.