John's Brain Dump

All the technical gyrations I go through to build software, so I don't forget them and others can benefit from them.

Receive Email Updates

June 2006 - Posts

Finding the Current and Last Page Numbers of a Crystal Report in ASP.NET 1.1

I've been banging my head for about a week on the problem of determining the last page number of a Crystal Report viewed through the web ReportViewer class. You would think that the report viewer class, which has methods like ShowLastPage and ShowNextPage would have properties like CurrentPageNumber and LastPageNumber, but alas, you would be wrong. So I had to roll my own implementation of these, which I think you may benefit from.

Here is the basic outline of the process that I followed to keep track of the current and last page numbers of the report:

  1. Create properties on the Web Form to store the values in viewstate. (I called mine CurrentPageNumber and LastPageNumber, and I gave CurrentPageNumber the default value of 1.)
  2. Set the ReportSource property of the CrystalReportViewer in the viewer's Init event. (You'll need to do this whether you use my method or not.)
  3. During the page's initial load (Not IsPostBack), call ShowLastPage on the report viewer.
  4. Create an event handler for the Navigate event of the report viewer. In that event handler, execute the following code:
If Not Me.IsPostBack Then ' Store the last page number in viewstate. Me.LastPageNumber = e.NewPageNumber ' Mark the event as handled, to prevent actual navigation. e.Handled = True Else ' Store the index of the page now being displayed. Me.CurrentPageNumber = e.NewPageNumber End If

That's the most efficient solution that I could think of to find these two values, assuming I need both of them through the entire lifecycle of the page. At some point, I'd like to create a class that extends CrystalReportViewer that includes these properties, but for right now, I'll settle for just keeping them on the page I'm working with.

kick it on dotnetkicks.com

UPDATE: 6/20/06

I can't really find an elegant solution that tells me when I am viewing the last page of a report. So after much hair-pulling, I opted for a dirty trick. An instance of the CrystalReportViewer class *knows* whether or not it is on the last page after its PreRender event fires. It doesn't expose this information, but that doesn't mean you can't get at it. Now I'll admit, this goes against every principle of OOP that I know, but sometimes, you gotta do what you gotta do.

You can call the QueryIsLastPageKnown method after the PreRender event of the report viewer fires. If you need to, you can write an event handler for the PreRender event of a control that follows the report viewer in your page. This will tell you whether or not your report viewer is displaying the last page in the report, while you still have time (just barely) to set values on controls that are based on this information.

Private Shared _reportAgentFieldInfo As System.Reflection.FieldInfo Private Shared _isLastPageNumberKnownFieldInfo As System.Reflection.FieldInfo Private Shared ReadOnly Property ReportAgentFieldInfo() As System.Reflection.FieldInfo Get If _reportAgentFieldInfo Is Nothing Then Dim reportViewerType As Type = GetType(CrystalDecisions.Web.CrystalReportViewer) Dim reportAgentType As Type = GetType(CrystalDecisions.Web.ReportAgent) For Each fieldInfo As Reflection.FieldInfo In reportViewerType.GetFields(Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic) If fieldInfo.FieldType.Equals(reportAgentType) Then _reportAgentFieldInfo = fieldInfo End If Next fieldInfo End If Return _reportAgentFieldInfo End Get End Property Private Shared ReadOnly Property IsLastPageNumberKnownFieldInfo() As System.Reflection.FieldInfo Get If _isLastPageNumberKnownFieldInfo Is Nothing Then Dim reportAgentType As Type = GetType(CrystalDecisions.Web.ReportAgent) _isLastPageNumberKnownFieldInfo = reportAgentType.GetField("m_bIsLastPageNumberKnown", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic) End If Return _isLastPageNumberKnownFieldInfo End Get End Property Private Shared Function QueryIsLastPageKnown(ByVal reportViewer As CrystalDecisions.Web.CrystalReportViewer) As Boolean ' ' HACK: This entire implementation is a hack, violating encapsulation of the CrystalDecisions.Web assembly. ' ' The CrystalDecisions.Web assembly knows whether or not the last page of a report is known, but does not reveal that information ' in any way that is accessable to other code. Therefore, the information is extracted via reflection of non-public members. ' ' If the CrystalDecisions.Web assembly is changed, this method should not cause the application to break. ' Rather, the current and last page numbers of a report will simply be displayed incorrectly. ' If Not ReportAgentFieldInfo Is Nothing Then Dim reportAgent As CrystalDecisions.Web.ReportAgent reportAgent = CType(ReportAgentFieldInfo.GetValue(reportViewer), CrystalDecisions.Web.ReportAgent) If (Not reportAgent Is Nothing) _ AndAlso (Not IsLastPageNumberKnownFieldInfo Is Nothing) Then Return CBool(IsLastPageNumberKnownFieldInfo.GetValue(reportAgent)) End If End If Return False End Function
Share this post: email it! | bookmark it! | digg it! | reddit! | kick it! | live it!
More Posts