65.9K
CodeProject is changing. Read more.
Home

Show GridView even if datasource is empty

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.21/5 (17 votes)

Feb 9, 2007

CPOL

2 min read

viewsIcon

175678

A simple method to show a GridView even if the datasource asigned is empty.

Introduction

I was recently faced with a problem where I used a GridView to add new data directly into the grid from the grid's footer, but found out that when there is no data (no rows in my DataTable) to show initially, the grid was not visible, and thus adding new data via the footer was not possible.

Solution Explanation

I wrote a simple method that adds an empty row to the GridView's DataSource then hides that row. Many examples out there shows this technique using the RowDataBound event; it works initially, but when doing a second postback, the empty row and its controls will show up again.

The Code

The method below takes the grid's DataSource and extracts the DataTable from it; it clones a copy and then adds an empty row. Cloning the DataTable will prevent you from adding an empty row inadvertently to your "Master" source.

You will notice two if statements; the first one will execute directly after you have assigned a source to your GridView, the second will execute on Page_Load.

/// =============================================================
/// <summary>
/// Show grid even if datasource is empty
/// <param name="grdView">GridView</param>
/// =============================================================
protected void EmptyGridFix(GridView grdView)
{
    // normally executes after a grid load method
    if (grdView.Rows.Count == 0 &&
        grdView.DataSource != null)
    {
        DataTable dt = null;
        
        // need to clone sources otherwise
        // it will be indirectly adding to 
        // the original source
        
        if (grdView.DataSource is DataSet)
        {
            dt = ((DataSet)grdView.DataSource).Tables[0].Clone();
        }
        else if (grdView.DataSource is DataTable)
        {
            dt = ((DataTable)grdView.DataSource).Clone();
        }

        if (dt == null)
        {
            return;
        }
        
        dt.Rows.Add(dt.NewRow()); // add empty row
        grdView.DataSource = dt;
        grdView.DataBind();        

        // hide row
        grdView.Rows[0].Visible = false;
        grdView.Rows[0].Controls.Clear();
    }

    // normally executes at all postbacks
    if (grdView.Rows.Count == 1 &&
        grdView.DataSource == null)
    {
        bool bIsGridEmpty = true;
        
        // check first row that all cells empty
        for (int i = 0; i < grdView.Rows[0].Cells.Count; i++)
        {
            if (grdView.Rows[0].Cells[i].Text != string.Empty)
            {
                bIsGridEmpty = false;
            }
        }
        // hide row
        if (bIsGridEmpty)
        {
            grdView.Rows[0].Visible = false;
            grdView.Rows[0].Controls.Clear();
        }
    }
}

Implementation

The method must be called on two occasions:

  1. Directly after assigning your DataSet or DataTable to your GridView
  2. On each Page_Load
public class MyPage : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        this.EmptyGridFix(grdYourGrid);
        
        if (!this.IsPostBack)
        {
            this.LoadGrid();
        }
    }

    protected void LoadGrid()
    {
        DataSet dsMyDataSet = null;

        // obtain dataset/datatable from DAL/BAL

        grdYourGrid.DataSource = dsMyDataSet.Table[0];
        grdYourGrid.DataBind();

        this.EmptyGridFix(grdYourGrid);
    }

    
    protected void EmptyGridFix(GridView grdView)
    {
        // method code comes here
    }

    // rest of page implementation would follow
}

Last words

The code above only works on instances where the GridView DataSource is being populated via a DataSet or DataTable, I have not tested any other sources.

A good idea is to create a class that would inherit from System.Web.UI.Page and drop the above method in there and have your pages inherit from that class.

I guess there are cleaner/better ways to implement this if... I can think of some really outrageous ways of fixing this stupid problem, like overloading the original GridView control. But one has to weigh the effort spent against the benefits. I really hope to see a fix in future versions of .NET.