Report writer

ReportWriterControl

Paginated, grouped reports from a Crystal-style XML definition, with a group tree, search, print and export.

Overview

ReportWriterControl renders a ReportDefinition as paginated HTML pages with Crystal-style group headers and footers, a clickable group tree and drill-down tabs. The definition is built in code or loaded from a Crystal XML export by CrystalXmlReportLoader, which reads the tables, joins, groups, formulas and field placement. The control has no data access of its own: the host registers IReportDataExecutor, IReportSessionContext and IReportPickListProvider in dependency injection, and optionally an IReportExporter. The toolbar prints, exports, searches the report text and zooms the pages.

Examples

#Model costs by community, model, group and phase

The bundled XML defines four group levels, each with a sum in its footer. Pick a model and a community and press Run; the report loads on arrival too. This site's data executor ignores the SQL in the definition and synthesises rows from the demo data, so every choice returns a report. Open the group tree on the left to jump between groups, or search the report text from the toolbar.

Example
Razor
C#
Report Groups

No groups available.

No report loaded.
Ready

Documentation

ReportWriterControl parameters

ParameterTypeDefaultDescription
ShowChromebooltrueToolbar, group tree, tabs and the parameter dialog. False drops the bare page area into a host that has its own UI.
UsePositionedLayoutboolfalseRenders with the Crystal band and object geometry instead of table columns, in ShowReportAsync, the parameter dialog and refresh.
PdfViewerComponentTypeType?nullThe PDF viewer component used for .rpt output, for trimmed hosts that bring the Documents package.
PromptOptionalParametersboolfalseIncludes optional parameters in the parameter dialog.
OnCloseEventCallback—The toolbar's Close button. Unset with ShowChrome on, the button is still there and does nothing.
OnPageTitleChangedEventCallback<string>—Raised by ShowReportAsync with the report's file name without extension, for a host's title bar.

Methods

MethodInputsReturnsDescription
ShowXmlReport()string xmlFilePath
Dictionary<string, object>? parameters = null
bool positioned = false
TaskLoads a Crystal XML export through CrystalXmlReportLoader, runs it with the given values and renders it; positioned keeps the band geometry. What this page calls.
ShowReportAsync()string file
IReadOnlyDictionary<string, string>? seedParameters = null
TaskThe unified load for an .rpt or .xml path: prompts for required parameters the seeds do not supply, raises OnPageTitleChanged, seeds a parameter named DivisionID from the session context, and treats seeds named Filter:Table.Field as field filters.
ShowSqlReport()ReportDefinition definition
Dictionary<string, object>? parameterValues = null
…
TaskExecutes a definition built in code through IReportDataExecutor and renders it. Session parameters listed in ReportOptions are filled in when the SQL names them and the caller did not.
ShowDataTableReport()string title
DataTable data
ReportOrientation orientation = ReportOrientation.Portrait
TaskRenders a table you already have as a report.
ShowCrystalReport()string rptFilePath
…
TaskA native .rpt file: needs IReportExporter, which renders it to PDF for the viewer. Logs a warning and shows nothing without one.
ShowDesignerReport()ReportDesignerDocument document
Dictionary<string, object>? parameters = null
TaskRuns a designer document as a snapshot, subreports included, without saving it.
ExportCrystalReport()string formatTask<byte[]?>The loaded .rpt as PDF, Excel, Word, RTF or CSV bytes through IReportExporter; null when none is registered.
Print()—TaskOpens the browser's print dialog for the rendered report.
Clear()—voidClears the report and its tabs.
GoToPage()int pageNumvoidShows that page, 1-based, of the active tab.
SwitchTab()int tabIndexvoidMakes that tab active.
CloseTab()int tabIndexvoidCloses a drill-down tab; the main report at index 0 cannot be closed.
OpenDrillDown()FxGroupNode node
List<DrillDownFilter> fullPath
TaskOpens, or switches to, a tab that re-queries with the node's path as an extra filter and shows the detail columns.
SetXmlSource()string xmlFilePathvoidTells the control which XML a definition came from, so drill-down tabs can re-parse it. Needed only before a direct ShowSqlReport.

State

PropertyTypeDefaultDescription
IsLoadingboolfalseTrue while a report is being loaded or run.
ReportLoadedboolfalseTrue once a report has rendered.
StatusMessagestring"Ready"The text in the status area.
ErrorMessagestring?nullThe last failure, shown in place of the pages.
TabsList<ReportTab>new()Open tabs; index 0 is the main report, drill-downs follow.
ActiveTabIndexint0The tab on display.
GroupTreeList<FxGroupNode>—The active tab's group tree.
DefinitionPostProcessorAction<ReportDefinition>?nullSettable. Runs on every definition the control builds for a drill-down tab, so a host repeats there what it did to the main definition.

Host services, resolved from dependency injection

PropertyTypeDefaultDescription
IReportDataExecutorDataTable Execute(string sql, IDictionary<string, object>? parameters)requiredRuns the SQL the loader builds and returns a DataTable. The host decides the data layer.
IReportSessionContextobject? Get(string parameterName)requiredTurns a session parameter name into a value, for the names listed in ReportOptions.SessionAutoInjectParameters.
IReportPickListProviderGetPickList(ReportParameter) / GetPickList(string) / HasPickList(string)requiredPick-list values for the parameter dialog, by ReportParameter (preferred, runs its PickListSql) or by name. EmptyReportPickListProvider ships for hosts without lists.
IReportViewerSettingsTask<int> GetZoomLevelAsync() / Task SetZoomLevelAsync(int)requiredPer-user zoom persistence; InMemoryReportViewerSettings ships as the default.
IReportExporterLoadReport, SetParameters, ExportToPdf / ExportToExcel / ExportToWord / ExportToRtf / ExportToCsvregisteredA Crystal Reports engine for native .rpt files only. Blazor cannot inject a missing service, so a host without Crystal registers a no-op.
ReportOptionsclasssingletonSingleton settings: SchemaPrefix (default dbo), SessionAutoInjectParameters, MaxRowsPerReport (100,000; 0 is unlimited), EagerGroupColumnsInMainQuery.

The toolbar's Print / Save as PDF uses the browser's print dialog, and its HTML, CSV and Excel data exports are the control's own (ReportNativeExport), so none of them need IReportExporter. This site registers ReportOptions with an empty schema prefix and DivisionID and UserId as session parameters, its own data executor and session context, the empty pick-list provider, the in-memory viewer settings and a no-op exporter.

An unhandled error has occurred. Reload 🗙

Rejoining the server...

Rejoin failed... trying again in seconds.

Failed to rejoin.
Please retry or reload the page.

The session has been paused by the server.

Failed to resume the session.
Please retry or reload the page.