After coming across the problem regarding not being able to see the header or footer of a GridView when the data source is empty, I have come up with a fairly clean solution (at least IMHO). I saw a couple other solutions in the forums that gave me some ideas
along with an article at
http://weblogs.asp.net/despos/archive/2005/06/30/416783.aspx that really got me pointed in the right direction. The one thing that I wanted to change about the aforementioned link was that no text was displayed to the user. While you could just add a
label above the grid and populate the text property of it when the data source is empty, I prefer to have the error message between the header and footer as I am used to with ASP Classic programming. The nice thing about this solution is that it doesn't require
the stored procedure or retrieval method to return a blank record as I saw in some other solutions.
I created a sub called BuildNoRecords that goes as follows:
Public Sub BuildNoRecords(ByVal gridView as GridView, ByVal ds as DataSet)
Try
If ds.Tables(0).Rows.Count = 0 Then
'Add a blank row to the dataset
ds.Tables(0).Rows.Add(ds.Tables(0).NewRow())
'Bind the DataSet to the GridView
gridView.DataSource = ds
gridView.DataBind()
'Get the number of columns to know what the Column Span should be
Dim columnCount as Integer = gridView.Rows(0).Cells.Count
'Call the clear method to clear out any controls that you use in the columns. I use a dropdown list in one of the column so this was necessary.
gridView.Rows(0).Cells.Clear()
gridView.Rows(0).Cells.Add(New TableCell)
gridView.Rows(0).Cells(0).ColumnSpan = columnCount
gridView.Rows(0).Cells(0).Text = "No Records Found."
End If
Catch ex as Exception
'Do your exception handling here
End Try
End Sub
I then call this sub after I fill my DataSet:
Dim ds as DataSet = Nothing
ds = obj.GetList()
'Call the Sub: gv is the GridView I have designed in the form designer.
BuildNoRecords(gv, ds)
I hope that this helps others who have had the same problem I did.
I accidentally left out a relatively key part of the code... oops!
The main If block "If ds.Tables(0).Rows.Count = 0 Then"
needs to have a Else statement for when the data source has records. It should read like this:
If ds.Tables(0).Rows.Count = 0 Then
'Add a blank row to the dataset
ds.Tables(0).Rows.Add(ds.Tables(0).NewRow())
'Bind the DataSet to the GridView
gridView.DataSource = ds
gridView.DataBind()
'Get the number of columns to know what the Column Span should be
Dim columnCount as Integer = gridView.Rows(0).Cells.Count
'Call the clear method to clear out any controls that you use in the columns. I use a dropdown list in one of the column so this was necessary.
gridView.Rows(0).Cells.Clear()
gridView.Rows(0).Cells.Add(New TableCell)
gridView.Rows(0).Cells(0).ColumnSpan = columnCount
gridView.Rows(0).Cells(0).Text = "No Records Found."
Else
gridView.DataSource = ds
gridView.DataBind()
End If
"ds = obj.GetList()" is a methid in its application that return a Dataset. in your case you should provide The dataSet that your GridView is Bind to it.
a more elegant solution, without tempering with the datasource, is creating a custom control that extends GridView and overriding CreateChildControls like so:
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 && ShowWhenEmpty)
{
//create table
Table table = new Table();
table.ID = this.ID;
//convert the exisiting columns into an array and initialize
DataControlField[] fields = new DataControlField[this.Columns.Count];
this.Columns.CopyTo(fields, 0);
if(this.ShowHeader)
{
//create a new header row
GridViewRow headerRow = base.CreateRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal);
this.InitializeRow(headerRow, fields);
table.Rows.Add(headerRow);
}
//create the empty row
GridViewRow emptyRow = new GridViewRow(-1, -1, DataControlRowType.EmptyDataRow, DataControlRowState.Normal);
TableCell cell = new TableCell();
cell.ColumnSpan = this.Columns.Count;
cell.Width = Unit.Percentage(100);
if(!String.IsNullOrEmpty(EmptyDataText))
cell.Controls.Add(new LiteralControl(EmptyDataText));
if(this.EmptyDataTemplate != null)
EmptyDataTemplate.InstantiateIn(cell);
emptyRow.Cells.Add(cell);
table.Rows.Add(emptyRow);
if(this.ShowFooter)
{
//create footer row
GridViewRow footerRow = base.CreateRow(-1, -1, DataControlRowType.Footer, DataControlRowState.Normal);
this.InitializeRow(footerRow, fields);
table.Rows.Add(footerRow);
}
this.Controls.Clear();
this.Controls.Add(table);
}
return numRows;
}
ShowWhenEmpty is a simple property that you set true to display headers and footers when empty:
[Category("Behaviour")]
[Themeable(true)]
[Bindable(BindableSupport.No)]
public bool ShowWhenEmpty
{
get
{
if (ViewState["ShowWhenEmpty"] == null)
ViewState["ShowWhenEmpty"] = false;
return (bool)ViewState["ShowWhenEmpty"];
}
set
{
ViewState["ShowWhenEmpty"] = value;
}
}
With this approach you will have the same formatting for the rows as if the database is not empty. Also, this will display EmptyDataText and EmptyDataTemplate.
I have converted this to VB.net (2.0) and get an error on the
this.InitializeRow(headerRow, fields);
or me.InitializeRow(headerRow, fields) as the VB i get an Object reference not set to an instance of an object error.Fields and headerRow are both something so i presume it is a property on one of those objects which is causing the problem? Have you come accross
this, any thoughts?
Cheers
here is the code - it has not been tested as the Me.InitializeRow(HeaderRow, Fields) line fails.
Also worth noting that i had trouble converting this line:
Dim fields() As
System.Web.UI.WebControls.DataControlField = New
System.Web.UI.WebControls.DataControlField(Me.Columns.Count) {}
and used an online c# converter, but least it compiles now? hopefully it is correct!
Dim NumRows As Integer = MyBase.CreateChildControls(dataSource, dataBinding)
If NumRows = 0 AndAlso
ShowWhenEmpty Then
Dim T As New System.Web.UI.WebControls.Table
T.ID = Me.ID
Dim fields() As
System.Web.UI.WebControls.DataControlField = New
System.Web.UI.WebControls.DataControlField(Me.Columns.Count) {}
Me.Columns.CopyTo(fields, 0)
'//convert the exisiting columns into an array and initialize
'DataControlField[] fields = new DataControlField[this.Columns.Count];
'this.Columns.CopyTo(fields, 0);
If Me.ShowHeader
Then
Dim HeaderRow
As System.Web.UI.WebControls.GridViewRow = MyBase.CreateRow(-1, -1, Web.UI.WebControls.DataControlRowType.Header, Web.UI.WebControls.DataControlRowState.Normal)
Me.InitializeRow(HeaderRow, Fields)
T.Rows.Add(HeaderRow)
End If
'Create Empty Row
Dim EmptyRow As New
System.Web.UI.WebControls.GridViewRow(-1, -1, Web.UI.WebControls.DataControlRowType.EmptyDataRow, Web.UI.WebControls.DataControlRowState.Normal)
Dim Cell As New System.Web.UI.WebControls.TableCell
Cell.ColumnSpan = Me.Columns.Count
Cell.Width = System.Web.UI.WebControls.Unit.Percentage(100)
If Not System.String.IsNullOrEmpty(EmptyDataText)
Then
Dim Lit As New System.Web.UI.WebControls.Literal
Lit.Text = Me.EmptyDataText
Cell.Controls.Add(Lit)
End If
If Not Me.EmptyDataTemplate Is Nothing Then
Me.EmptyDataTemplate.InstantiateIn(Cell)
End If
EmptyRow.Cells.Add(Cell)
T.Rows.Add(EmptyRow)
'Create footer row
Dim FooterRow As System.Web.UI.WebControls.GridViewRow
FooterRow = MyBase.CreateRow(-1, -1, Web.UI.WebControls.DataControlRowType.Footer, Web.UI.WebControls.DataControlRowState.Normal)
Me.InitializeRow(FooterRow, Fields)
T.Rows.Add(FooterRow)
Me.Controls.Clear()
Me.Controls.Add(T)
tmgneuguy
Member
40 Points
8 Posts
Solution: Show Header/Footer of Gridview with Empty Data Source
Feb 06, 2006 04:20 AM|LINK
I created a sub called BuildNoRecords that goes as follows:
Public Sub BuildNoRecords(ByVal gridView as GridView, ByVal ds as DataSet)
Try
If ds.Tables(0).Rows.Count = 0 Then
'Add a blank row to the dataset
ds.Tables(0).Rows.Add(ds.Tables(0).NewRow())
'Bind the DataSet to the GridView
gridView.DataSource = ds
gridView.DataBind()
'Get the number of columns to know what the Column Span should be
Dim columnCount as Integer = gridView.Rows(0).Cells.Count
'Call the clear method to clear out any controls that you use in the columns. I use a dropdown list in one of the column so this was necessary.
gridView.Rows(0).Cells.Clear()
gridView.Rows(0).Cells.Add(New TableCell)
gridView.Rows(0).Cells(0).ColumnSpan = columnCount
gridView.Rows(0).Cells(0).Text = "No Records Found."
End If
Catch ex as Exception
'Do your exception handling here
End Try
End Sub
I then call this sub after I fill my DataSet:
Dim ds as DataSet = Nothing
ds = obj.GetList()
'Call the Sub: gv is the GridView I have designed in the form designer.
BuildNoRecords(gv, ds)
I hope that this helps others who have had the same problem I did.
tmgneuguy
Member
40 Points
8 Posts
Re: Solution: Show Header/Footer of Gridview with Empty Data Source
Feb 08, 2006 11:32 AM|LINK
The main If block "If ds.Tables(0).Rows.Count = 0 Then" needs to have a Else statement for when the data source has records. It should read like this:
If ds.Tables(0).Rows.Count = 0 Then
'Add a blank row to the dataset
ds.Tables(0).Rows.Add(ds.Tables(0).NewRow())
'Bind the DataSet to the GridView
gridView.DataSource = ds
gridView.DataBind()
'Get the number of columns to know what the Column Span should be
Dim columnCount as Integer = gridView.Rows(0).Cells.Count
'Call the clear method to clear out any controls that you use in the columns. I use a dropdown list in one of the column so this was necessary.
gridView.Rows(0).Cells.Clear()
gridView.Rows(0).Cells.Add(New TableCell)
gridView.Rows(0).Cells(0).ColumnSpan = columnCount
gridView.Rows(0).Cells(0).Text = "No Records Found."
Else
gridView.DataSource = ds
gridView.DataBind()
End If
Sorry for any confusion.
TonyS
Member
125 Points
25 Posts
Re: Solution: Show Header/Footer of Gridview with Empty Data Source
May 26, 2006 09:00 PM|LINK
I have a question I am trying to incorporate this into my app and I am not sure what to use for the term obj in the line
ds = obj.GetList()
Can you please clarify?
Thanks
DonalDorling
Member
190 Points
38 Posts
Re: Solution: Show Header/Footer of Gridview with Empty Data Source
Jun 28, 2006 03:03 PM|LINK
Thanks
Donald
FrenchiInLA
Member
332 Points
99 Posts
Re: Solution: Show Header/Footer of Gridview with Empty Data Source
Jun 29, 2006 02:24 AM|LINK
"ds = obj.GetList()" is a methid in its application that return a Dataset. in your case you should provide The dataSet that your GridView is Bind to it.
CISCBrain
Member
97 Points
22 Posts
Re: Solution: Show Header/Footer of Gridview with Empty Data Source
Jul 26, 2006 07:58 AM|LINK
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 && ShowWhenEmpty) { //create table Table table = new Table(); table.ID = this.ID; //convert the exisiting columns into an array and initialize DataControlField[] fields = new DataControlField[this.Columns.Count]; this.Columns.CopyTo(fields, 0); if(this.ShowHeader) { //create a new header row GridViewRow headerRow = base.CreateRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal); this.InitializeRow(headerRow, fields); table.Rows.Add(headerRow); } //create the empty row GridViewRow emptyRow = new GridViewRow(-1, -1, DataControlRowType.EmptyDataRow, DataControlRowState.Normal); TableCell cell = new TableCell(); cell.ColumnSpan = this.Columns.Count; cell.Width = Unit.Percentage(100); if(!String.IsNullOrEmpty(EmptyDataText)) cell.Controls.Add(new LiteralControl(EmptyDataText)); if(this.EmptyDataTemplate != null) EmptyDataTemplate.InstantiateIn(cell); emptyRow.Cells.Add(cell); table.Rows.Add(emptyRow); if(this.ShowFooter) { //create footer row GridViewRow footerRow = base.CreateRow(-1, -1, DataControlRowType.Footer, DataControlRowState.Normal); this.InitializeRow(footerRow, fields); table.Rows.Add(footerRow); } this.Controls.Clear(); this.Controls.Add(table); } return numRows; }ShowWhenEmpty is a simple property that you set true to display headers and footers when empty:With this approach you will have the same formatting for the rows as if the database is not empty. Also, this will display EmptyDataText and EmptyDataTemplate.
OblivionSY
Member
39 Points
16 Posts
Re: Solution: Show Header/Footer of Gridview with Empty Data Source
Jul 26, 2006 02:43 PM|LINK
I have converted this to VB.net (2.0) and get an error on the
this.InitializeRow(headerRow, fields);
or me.InitializeRow(headerRow, fields) as the VB i get an Object reference not set to an instance of an object error.Fields and headerRow are both something so i presume it is a property on one of those objects which is causing the problem? Have you come accross this, any thoughts?
Cheers
CISCBrain
Member
97 Points
22 Posts
Re: Solution: Show Header/Footer of Gridview with Empty Data Source
Jul 26, 2006 02:58 PM|LINK
OblivionSY
Member
39 Points
16 Posts
Re: Solution: Show Header/Footer of Gridview with Empty Data Source
Jul 26, 2006 04:10 PM|LINK
Also worth noting that i had trouble converting this line:
Dim fields() As System.Web.UI.WebControls.DataControlField = New System.Web.UI.WebControls.DataControlField(Me.Columns.Count) {}
and used an online c# converter, but least it compiles now? hopefully it is correct!
Dim NumRows As Integer = MyBase.CreateChildControls(dataSource, dataBinding)
If NumRows = 0 AndAlso ShowWhenEmpty Then
Dim T As New System.Web.UI.WebControls.Table
T.ID = Me.ID
Dim fields() As System.Web.UI.WebControls.DataControlField = New System.Web.UI.WebControls.DataControlField(Me.Columns.Count) {}
Me.Columns.CopyTo(fields, 0)
'//convert the exisiting columns into an array and initialize
'DataControlField[] fields = new DataControlField[this.Columns.Count];
'this.Columns.CopyTo(fields, 0);
If Me.ShowHeader Then
Dim HeaderRow As System.Web.UI.WebControls.GridViewRow = MyBase.CreateRow(-1, -1, Web.UI.WebControls.DataControlRowType.Header, Web.UI.WebControls.DataControlRowState.Normal)
Me.InitializeRow(HeaderRow, Fields)
T.Rows.Add(HeaderRow)
End If
'Create Empty Row
Dim EmptyRow As New System.Web.UI.WebControls.GridViewRow(-1, -1, Web.UI.WebControls.DataControlRowType.EmptyDataRow, Web.UI.WebControls.DataControlRowState.Normal)
Dim Cell As New System.Web.UI.WebControls.TableCell
Cell.ColumnSpan = Me.Columns.Count
Cell.Width = System.Web.UI.WebControls.Unit.Percentage(100)
If Not System.String.IsNullOrEmpty(EmptyDataText) Then
Dim Lit As New System.Web.UI.WebControls.Literal
Lit.Text = Me.EmptyDataText
Cell.Controls.Add(Lit)
End If
If Not Me.EmptyDataTemplate Is Nothing Then
Me.EmptyDataTemplate.InstantiateIn(Cell)
End If
EmptyRow.Cells.Add(Cell)
T.Rows.Add(EmptyRow)
'Create footer row
Dim FooterRow As System.Web.UI.WebControls.GridViewRow
FooterRow = MyBase.CreateRow(-1, -1, Web.UI.WebControls.DataControlRowType.Footer, Web.UI.WebControls.DataControlRowState.Normal)
Me.InitializeRow(FooterRow, Fields)
T.Rows.Add(FooterRow)
Me.Controls.Clear()
Me.Controls.Add(T)
Return NumRows
End If
End Function
drodrig
Member
45 Points
9 Posts
Re: Solution: Show Header/Footer of Gridview with Empty Data Source
Jul 27, 2006 03:00 PM|LINK
This code work fine to show ViewGrid, but when I access to FooterRow or HeaderRow properties after all page has loaded, I get a null reference.
Do you know why?
Thank you
drodrig