When using this approach to get header & footer visible when there is no record, it works. Except for one thing. If I've got a Button in the footer, its Click event will not fire. Any ideas?
I really can't understand why MS did not implement the ability to display a footer/header when the grid is empty.
Anyway, I had problems with the GridViewEx when having input controls in the footer. They do not maintain viewstate on postbacks. Therefore I did a little tweak to solve that:
The ViewState is maintained because the footer is not the same footer as the original footer. As you can see in the code, there is newly created footer named _footerRow2. Therefore the viewstate will not be kept on postback. To fix this simply add a new
readonly property exposing the _footerRow2. This way it is possible to find the controls in the new footer (using myGrid.FooterRowEmpty.findControls("NameOfInputField") and setting the values manually. If using the myGrid.FooterRow, you will find the controls,
but they will of course not be visible.
Here is the code for the property:
public virtual GridViewRow FooterRowEmpty
{
get
{
if (_footerRow2 == null)
{
EnsureChildControls();
}
return _footerRow2;
}
}
And here is the usage on the footerrows:
Private Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.PreRender
If Not grdData Is Nothing Then
Dim footerRow As GridViewRow = grdData.FooterRow
If grdData.Rows.Count = 0 AndAlso Not grdData.FooterRowEmpty Is Nothing Then
footerRow = grdData.FooterRowEmpty
LoadFilterValues(footerRow) 'Put values into the fields in the footer.
SetDefaultButtonAndFocus(footerRow)
ElseIf Not footerRow Is Nothing Then
SetDefaultButtonAndFocus(footerRow)
End If
End If
End Sub
This code will put the values back in the controls (LoadFilterValues) and set default button and focus (SetDefaultButtonAndFocus). You will have to write these yourself ;)
Sounds as if your issue may be the same or related to mine - but just to check..
For several years I have used the relatively crude approach of declaring a GridView with a FooterTemplate on each column for inserts and an EmptyDataTemplate containing identical controls for inserting when there is no starting data. Then in code behind
I test if the row count is 0 and if so find each control from the EmptyData template and if not do the same for the FooterRow. All works but very irritating.
I have never been interested in any crude hack such as binding to an empty DataTable. So now I am trying to build a custom GridView using the approach to override CreateChildControls broadly as set out by CISCBrain with a few slight modifications (in addition
I am also autogenerating command columns but these work OK so I have removed this processing from the code below).
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 (ShowHeaderWhenEmpty Or ShowFooterWhenEmpty) Then
Dim tab As Table = Me.CreateChildTable()
Dim flds As DataControlField() = New DataControlField(Me.Columns.Count - 1) {}
Me.Columns.CopyTo(flds, 0)
If ShowHeaderWhenEmpty Then
_headerRow = MyBase.CreateRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal)
Me.InitializeRow(_headerRow, flds)
tab.Rows.Add(_headerRow)
MyBase.OnRowCreated(New GridViewRowEventArgs(_headerRow))
End If
If Insertable And ShowFooterWhenEmpty Then
_footerRow = MyBase.CreateRow(-1, -1, DataControlRowType.Footer, DataControlRowState.Normal)
Me.InitializeRow(_footerRow, flds)
Me.ShowFooter = True
tab.Rows.Add(_footerRow)
MyBase.OnRowCreated(New GridViewRowEventArgs(_footerRow))
End If
Me.Controls.Clear()
Me.Controls.Add(tab)
End If
Return numRows
End Function
And I have the following properties:
Protected _headerRow As GridViewRow = Nothing
Public Overloads Overrides ReadOnly Property HeaderRow() As GridViewRow
Get
If Not MyBase.HeaderRow Is Nothing Then
Return MyBase.HeaderRow
Else
Return _headerRow
End If
End Get
End Property
Protected _footerRow As GridViewRow = Nothing
Public Overloads Overrides ReadOnly Property FooterRow() As GridViewRow
Get
If Not MyBase.FooterRow Is Nothing Then
Return MyBase.FooterRow
Else
Return _footerRow
End If
End Get
End Property
All this works and I can retrieve values from the controls in the footer row whether there is starting data or not.
However, the problem I have is if the footer includes databound controls such as DropDownLists. In this case, I get an error that the Bind (or Eval) can only be used in the context of a databound control. This did not happen when I was using the EmptyDataTemplate
for this purpose, so it would seem that somehow the footer row is not getting initialized properly. What do I need to do to ensure that the footer is properly initialized and databound? Does your code for maintaining viewstate on postbacks relate to my issue?
Hopefully there is a solution which can be handled in the custom GridView class rather than requiring specific page code to initialize the footer - if the latter is the case then I am really back to square one as even the EmptyDataTemplate approach did this
declaratively.
Billyhole
Member
7 Points
28 Posts
Re: GridViewEx
Aug 15, 2007 08:43 PM|LINK
Hey can you help me out? What is the correction for the "BLOCKED EXPRESSION" stuff? Thanks.
cruster
Member
37 Points
14 Posts
Re: GridViewEx
Aug 16, 2007 12:53 PM|LINK
ViagraFalls
Member
248 Points
56 Posts
Re: GridViewEx
Aug 20, 2007 09:10 AM|LINK
One of them is
if (sortAttribute.IndexOf(e.SortExpression) > 0 || sortAttribute.Startswith(e.SortExpression))
Not sure what the other one is, as I'm at work, but it's something starting with expression.
rohit.rokade
Member
5 Points
35 Posts
Re: GridViewEx
Jun 16, 2008 11:12 AM|LINK
There is no need to do all these things if you are using Sqldatasource then just do the following thing,
1) Insert new row in sqldatasource
2) and just after that set gridview's edit index=0,
So, it will open that newly added blank row in edit mode and thats all.
proturbo
Member
46 Points
11 Posts
Re: GridViewEx
Feb 19, 2009 09:19 AM|LINK
Great class!
I really can't understand why MS did not implement the ability to display a footer/header when the grid is empty.
Anyway, I had problems with the GridViewEx when having input controls in the footer. They do not maintain viewstate on postbacks. Therefore I did a little tweak to solve that:
The ViewState is maintained because the footer is not the same footer as the original footer. As you can see in the code, there is newly created footer named _footerRow2. Therefore the viewstate will not be kept on postback. To fix this simply add a new readonly property exposing the _footerRow2. This way it is possible to find the controls in the new footer (using myGrid.FooterRowEmpty.findControls("NameOfInputField") and setting the values manually. If using the myGrid.FooterRow, you will find the controls, but they will of course not be visible.
Here is the code for the property:
public virtual GridViewRow FooterRowEmpty { get { if (_footerRow2 == null) { EnsureChildControls(); } return _footerRow2; } }And here is the usage on the footerrows:
This code will put the values back in the controls (LoadFilterValues) and set default button and focus (SetDefaultButtonAndFocus). You will have to write these yourself ;)jstranger
Member
290 Points
157 Posts
Re: GridViewEx
Sep 27, 2009 07:58 AM|LINK
Sounds as if your issue may be the same or related to mine - but just to check..
For several years I have used the relatively crude approach of declaring a GridView with a FooterTemplate on each column for inserts and an EmptyDataTemplate containing identical controls for inserting when there is no starting data. Then in code behind I test if the row count is 0 and if so find each control from the EmptyData template and if not do the same for the FooterRow. All works but very irritating.
I have never been interested in any crude hack such as binding to an empty DataTable. So now I am trying to build a custom GridView using the approach to override CreateChildControls broadly as set out by CISCBrain with a few slight modifications (in addition I am also autogenerating command columns but these work OK so I have removed this processing from the code below).
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 (ShowHeaderWhenEmpty Or ShowFooterWhenEmpty) Then
Dim tab As Table = Me.CreateChildTable()
Dim flds As DataControlField() = New DataControlField(Me.Columns.Count - 1) {}
Me.Columns.CopyTo(flds, 0)
If ShowHeaderWhenEmpty Then
_headerRow = MyBase.CreateRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal)
Me.InitializeRow(_headerRow, flds)
tab.Rows.Add(_headerRow)
MyBase.OnRowCreated(New GridViewRowEventArgs(_headerRow))
End If
If Insertable And ShowFooterWhenEmpty Then
_footerRow = MyBase.CreateRow(-1, -1, DataControlRowType.Footer, DataControlRowState.Normal)
Me.InitializeRow(_footerRow, flds)
Me.ShowFooter = True
tab.Rows.Add(_footerRow)
MyBase.OnRowCreated(New GridViewRowEventArgs(_footerRow))
End If
Me.Controls.Clear()
Me.Controls.Add(tab)
End If
Return numRows
End Function
And I have the following properties:
Protected _headerRow As GridViewRow = Nothing
Public Overloads Overrides ReadOnly Property HeaderRow() As GridViewRow
Get
If Not MyBase.HeaderRow Is Nothing Then
Return MyBase.HeaderRow
Else
Return _headerRow
End If
End Get
End Property
Protected _footerRow As GridViewRow = Nothing
Public Overloads Overrides ReadOnly Property FooterRow() As GridViewRow
Get
If Not MyBase.FooterRow Is Nothing Then
Return MyBase.FooterRow
Else
Return _footerRow
End If
End Get
End Property
All this works and I can retrieve values from the controls in the footer row whether there is starting data or not.
However, the problem I have is if the footer includes databound controls such as DropDownLists. In this case, I get an error that the Bind (or Eval) can only be used in the context of a databound control. This did not happen when I was using the EmptyDataTemplate for this purpose, so it would seem that somehow the footer row is not getting initialized properly. What do I need to do to ensure that the footer is properly initialized and databound? Does your code for maintaining viewstate on postbacks relate to my issue? Hopefully there is a solution which can be handled in the custom GridView class rather than requiring specific page code to initialize the footer - if the latter is the case then I am really back to square one as even the EmptyDataTemplate approach did this declaratively.
Jon