问题
I'm stuck with the following problem. I'm trying to implement a basic GridView paged result set, which connects to an Oracle database. By itself, the GridView, and the paged results, work fine. The problem comes when I try to put it in page layout class that we have at work.
We have ClassA, which inherits from Page, and is a corporate standard. Then I have ClassB, which inherits from ClassA and which includes application-specific code. The page that the GridView is on inherits from ClassB. This all seems to work fine in other pages, and I don't think it's the source of the problem, but I thought I'd mention it.
What happens is that the first time the page with the GridView loads, everything looks normal. The query runs and the first 10 records are displayed, with the numbers for paging below. When I click on "2" or any of the other pages, I get the "yellow screen of death" with the following message: "Object reference not set to an instance of an object". The object being referred to in that error line is "Me", the Page object (ASP.pagename_aspx in the debugger). I don't believe that the exact line it fails on is that important, because I've switched the order of a few statements around and it just fails on the earliest one.
I've traced through with the debugger and it looks normal, only that on Page 1 it works fine, and Page 2 it fails.
I have implemented the PageIndexChanging event (again, it works by itself if I remove inheritance from ClassB. Also, if I try inheriting directly from ClassA (bypassing ClassB entirely), I still get the problem.
Any ideas? Thanks.
回答1:
I ran into a similar situation where the base (ClassA in your example) had variables that were set up to handle all the paging and sorting bits, and the GridView was wired up to events that used those variables. Not setting the proper base class variables in my page caused the exact same sort of error.
回答2:
When I've had similar problems in the past, it has usually been a databinding problem (not calling DataBind() at the right time so when it tries to look at the next page the DataSource is null).
回答3:
I agree with @DotNetDaddy in that you need to make sure you set the datasource on post-back, as this is almost certainly the reason for the "fun" yellow screen of death. The below is a very simple example that shows sorting and paging for a GridView in .NET 2.0+
The below is the exact markup required for this gridview to work correctly w/ my vb code
<asp:GridView ID="gridSuppliers" EnableViewState="false" runat="server" OnPageIndexChanging="gridSuppliers_PageIndexChanging" AutoGenerateColumns="false" AllowPaging="true" AllowSorting="true" CssClass="datatable" CellPadding="0" CellSpacing="0" BorderWidth="0" GridLines="None">...</asp:GridView>
Next is the code-behind file w/ the required sorting/paging implementation for a collection based databind
Partial Public Class _Default
Inherits System.Web.UI.Page
Implements ISupplierView
Private presenter As SupplierPresenter
Protected Overrides Sub OnInit(ByVal e As System.EventArgs)
MyBase.OnInit(e)
presenter = New SupplierPresenter(Me)
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
presenter.OnViewLoad()
End Sub
Protected Sub gridSuppliers_PageIndexChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewPageEventArgs) Handles gridSuppliers.PageIndexChanging
gridSuppliers.PageIndex = e.NewPageIndex
presenter.PopulateSupplierList()
End Sub
Private Sub gridSuppliers_Sorting(ByVal sender As Object, ByVal e As GridViewSortEventArgs) Handles gridSuppliers.Sorting
If DirectCast(ViewState("PreviousSortExpression"), String) = e.SortExpression Then
If DirectCast(ViewState("PreviousSortDirection"), String) = "Ascending" Then
e.SortDirection = System.Web.UI.WebControls.SortDirection.Descending
ViewState("PreviousSortDirection") = "Descending"
Else
e.SortDirection = System.Web.UI.WebControls.SortDirection.Ascending
ViewState("PreviousSortDirection") = "Ascending"
End If
Else
e.SortDirection = System.Web.UI.WebControls.SortDirection.Ascending
ViewState("PreviousSortDirection") = "Ascending"
End If
ViewState("PreviousSortExpression") = e.SortExpression
Dim gv As GridView = DirectCast(sender, GridView)
If e.SortExpression.Length > 0 Then
For Each field As DataControlField In gv.Columns
If field.SortExpression = e.SortExpression Then
ViewState("PreviousHeaderIndex") = gv.Columns.IndexOf(field)
Exit For
End If
Next
End If
presenter.PopulateSupplierList()
End Sub
#Region "ISupplierView Properties"
Private ReadOnly Property PageIsPostBack() As Boolean Implements ISupplierView.PageIsPostBack
Get
Return Page.IsPostBack
End Get
End Property
Private ReadOnly Property SortExpression() As String Implements ISupplierView.SortExpression
Get
If ViewState("PreviousSortExpression") Is Nothing Then
ViewState("PreviousSortExpression") = "CompanyName"
End If
Return DirectCast(ViewState("PreviousSortExpression"), String)
End Get
End Property
Public ReadOnly Property SortDirection() As String Implements Library.ISupplierView.SortDirection
Get
If ViewState("PreviousSortDirection") Is Nothing Then
ViewState("PreviousSortDirection") = "Ascending"
End If
Return DirectCast(ViewState("PreviousSortDirection"), String)
End Get
End Property
Public Property Suppliers() As System.Collections.Generic.List(Of Library.Supplier) Implements Library.ISupplierView.Suppliers
Get
Return DirectCast(gridSuppliers.DataSource(), List(Of Supplier))
End Get
Set(ByVal value As System.Collections.Generic.List(Of Library.Supplier))
gridSuppliers.DataSource = value
gridSuppliers.DataBind()
End Set
End Property
#End Region
End Class
And finally, the presenter class used in the code-behind
Public Class SupplierPresenter
Private mView As ISupplierView
Private mSupplierService As ISupplierService
Public Sub New(ByVal View As ISupplierView)
Me.New(View, New SupplierService())
End Sub
Public Sub New(ByVal View As ISupplierView, ByVal SupplierService As ISupplierService)
mView = View
mSupplierService = SupplierService
End Sub
Public Sub OnViewLoad()
If mView.PageIsPostBack = False Then
PopulateSupplierList()
End If
End Sub
Public Sub PopulateSupplierList()
Try
Dim SupplierList As List(Of Supplier) = mSupplierService.GetSuppliers()
SupplierList.Sort(New GenericComparer(Of Supplier)(mView.SortExpression, mView.SortDirection))
mView.Suppliers = SupplierList
Catch ex As Exception
Throw ex
End Try
End Sub
End Class
**the class required to sort a generic collection that is referenced in the presenter
Imports System.Reflection
Imports System.Web.UI.WebControls
Public Class GenericComparer(Of T)
Implements IComparer(Of T)
Private mDirection As String
Private mExpression As String
Public Sub New(ByVal Expression As String, ByVal Direction As String)
mExpression = Expression
mDirection = Direction
End Sub
Public Function Compare(ByVal x As T, ByVal y As T) As Integer Implements System.Collections.Generic.IComparer(Of T).Compare
Dim propertyInfo As PropertyInfo = GetType(T).GetProperty(mExpression)
Dim obj1 As IComparable = DirectCast(propertyInfo.GetValue(x, Nothing), IComparable)
Dim obj2 As IComparable = DirectCast(propertyInfo.GetValue(y, Nothing), IComparable)
If mDirection = "Ascending" Then
Return obj1.CompareTo(obj2)
Else
Return obj2.CompareTo(obj1)
End If
End Function
End Class
回答4:
I lost my original unregistered login which I used to post this question.
Anyway, Harper Shelby's answer turned out to be correct. There was an unset variable in that base class (a custom object that is our corporate standard) that caused the problem (and no helpful error message).
If an admin, or someone with the right powers sees this, you could mark Harper's answer as the one, and close this. Thanks to everyone for their help.
来源:https://stackoverflow.com/questions/121828/problem-with-a-gridview-paging-and-object-reference-not-set-error