Skip to main content Skip to footer

How to Embed a Report Viewer in a .NET 9 WinForms App

  • 0 Comments
Quick Start Guide
What You Will Need

Visual Studio 2022

.NET 9.0 SDK

ActiveReports.NET NuGet packages

Controls Referenced

ActiveReports.NET WinForms Viewer

Tutorial Concept

Embed the ActiveReports WinForms Viewer in a .NET 9 application and load reports in RDLX and RPX formats from multiple storage options.

This guide provides a comprehensive walkthrough for integrating the ActiveReports.NET WinForms Report Viewer into a .NET 9.0 Windows Forms application in Visual Studio 2022. It covers everything from setting up the development environment and installing necessary NuGet packages to embedding the viewer control and dynamically loading reports.

Special attention is given to supporting both RDLX (Page Reports) and RPX (Section Reports) formats, with a focus on loading these reports from embedded resources for cleaner deployment. The guide also includes best practices for handling multiple report types with maintainable code patterns, ensuring a robust and flexible reporting integration for modern WinForms applications.

Here are the steps we will cover in this tutorial:

Here is our functional sample project.

Ready to check it out? Download ActiveReports.NET Today!

Project Setup and NuGet Installation

  1. Create a .NET 9 WinForms Project: In Visual Studio 2022 (or newer), create a new Windows Forms App targeting .NET 9.0 (ensure the project’s target framework is set to net9.0-windows for WinForms support). ActiveReports 19 fully supports .NET 5+ (including .NET 9) via its NuGet packages.
  2. Install ActiveReports NuGet Packages: Use the NuGet Package Manager to add MESCIUS.ActiveReports.Viewer.Win. In Visual Studio’s Package Manager Console, you can run:
Install-Package MESCIUS.ActiveReports.Viewer.Win

This will pull in all required ActiveReports assemblies (such as the core reporting engine and viewer). After installation, open the Windows Forms Designer (e.g. Form1.cs) to verify that the ActiveReports 19 toolbox tab appears with the Viewer control. If you don’t see it, ensure the NuGet package was added successfully and rebuild the project.

Toolbox Viewer

Adding the ActiveReports Viewer Control to the Form

  1. Drag the Viewer onto the Form: In the Form’s designer, find the Viewer control under the ActiveReports tab in the Toolbox. Drag and drop the Viewer control onto your form. This adds a GrapeCity.ActiveReports.Viewer.Win.Viewer component, typically named viewer1 by default.
  2. Dock the Viewer (Optional): For a full-page report preview, select the viewer control and set its Dock property to Fill. This will make the viewer expand to fill the form’s client area, ensuring the entire toolbar and report canvas are visible.
  3. Form Load Event: Double-click the Form’s title bar (or manually create a Form_Load event handler). In this event, you will load and run the report so that it displays when the form opens. 

Form Load Event

Loading an RDLX (Page) Report at Runtime

RDLX reports are the XML-based page report format in ActiveReports (similar to RDL). To load an RDLX report file into the viewer at runtime:

  • Ensure you have an RDLX report file available (designed in the ActiveReports Designer or created beforehand). Use the PageReport class to load the report definition and create a PageDocument for viewing.
  • Code (C#): In the Form_Load event (or your chosen place), add code to load the RDLX file and display it. For example:
// Path to the .rdlx report definition file
string filePath = @"C:\Reports\ReportName.rdlx";

// Load the RDLX report definition into a PageReport
var pageReport = new GrapeCity.ActiveReports.PageReport(new System.IO.FileInfo(filePath));

// Create a runnable PageDocument from the PageReport
var pageDocument = new GrapeCity.ActiveReports.Document.PageDocument(pageReport);

// Load the document into the viewer control
viewer1.LoadDocument(pageDocument);

In this code, PageReport loads the report layout from the file, and PageDocument prepares the report for rendering. Finally, viewer1.LoadDocument(pageDocument) displays the report in the viewer. (You can also call viewer1.LoadDocument(pageReport) directly, but using a PageDocument allows you to manipulate or inspect the document if needed before viewing.)

Loading an RPX (Section) Report at Runtime

RPX reports are XML-based Section report layouts (the older banded-section report format). Loading an RPX involves using the SectionReport class:

  • Make sure the RPX file is included or accessible. Unlike page reports, section reports do not require a separate document class; the SectionReport itself will be run and displayed.
  • Code (C#): To load a Section report from an RPX file at runtime:
// Path to the .rpx section report file
string filePath = @"C:\Reports\SectionReport1.rpx";

// Create a new SectionReport instance
var sectionReport = new GrapeCity.ActiveReports.SectionReport();

// Load the report layout from the RPX (XML) file
using (var xtr = new System.Xml.XmlTextReader(filePath))
{
    sectionReport.LoadLayout(xtr);
}

// Display the section report in the viewer
viewer1.LoadDocument(sectionReport);

Here we open the RPX file with an XmlTextReader and call sectionReport.LoadLayout(...) to load the report definition. Then viewer1.LoadDocument(sectionReport) runs the report and shows it in the viewer. (If you had a code-based SectionReport class instead, you could simply instantiate it and call LoadDocument(sectionReport) directly.)

Loading Reports from Embedded Resources

Rather than deploying external .rdlx/.rpx files, you can embed the report definitions in your application assembly:

  • Embed the Report: Add the .RDLX or .RPX file to your project (for example, place it in a folder like Reports in your solution). In the file’s properties, set Build Action to Embedded Resource. This will compile the report file into your application’s DLL.
  • Load from Assembly Resources: At runtime, retrieve the embedded report stream from your assembly and load it into the viewer. For example:
// Assume reportName is "Reports.InvoiceReport.rdlx" or ".rpx"
string reportResource = "MyApp.Reports.InvoiceReport.rdlx";
var asm = System.Reflection.Assembly.GetExecutingAssembly();

using (var stream = asm.GetManifestResourceStream(reportResource))
{
    if (reportResource.EndsWith(".rdlx", StringComparison.OrdinalIgnoreCase))
    {
        // For RDLX: load via PageReport using a TextReader
        using var reader = new System.IO.StreamReader(stream);
        var pageReport = new GrapeCity.ActiveReports.PageReport(reader);
        viewer1.LoadDocument(new GrapeCity.ActiveReports.Document.PageDocument(pageReport));
    }
    else if (reportResource.EndsWith(".rpx", StringComparison.OrdinalIgnoreCase))
    {
        // For RPX: load via SectionReport using an XmlReader
        using var xmlReader = System.Xml.XmlReader.Create(stream);
        var sectionReport = new GrapeCity.ActiveReports.SectionReport();
        sectionReport.LoadLayout(xmlReader);
        viewer1.LoadDocument(sectionReport);
    }
}

In this code, we use Assembly.GetExecutingAssembly().GetManifestResourceStream(...) to obtain the embedded file. For an RDLX resource, we wrap the stream with a StreamReader (since PageReport can accept a TextReader) and then create a PageReport and PageDocument as before. For an RPX resource, we use an XmlReader to load the layout into a SectionReport. Finally, the appropriate document is loaded into the viewer.

Tip: Ensure the resource name (including namespace/folder) is correct when calling GetManifestResourceStream. You can use asm.GetManifestResourceNames() to debug the exact resource name if needed.

Handling Both RDLX and RPX Formats Cleanly

To support both report formats in a maintainable way, you can encapsulate the loading logic. For example, write a helper method that takes a report name or path and handles the format internally:

void LoadReportIntoViewer(string reportPathOrResource, bool fromResource = false)
{
    Stream reportStream = fromResource 
        ? Assembly.GetExecutingAssembly().GetManifestResourceStream(reportPathOrResource) 
        : File.OpenRead(reportPathOrResource);
    if (reportStream == null) throw new FileNotFoundException("Report not found: " + reportPathOrResource);

    using (reportStream)
    {
        if (reportPathOrResource.EndsWith(".rdlx", StringComparison.OrdinalIgnoreCase))
        {
            // Load RDLX format
            using var reader = new StreamReader(reportStream);
            var pageReport = new GrapeCity.ActiveReports.PageReport(reader);
            viewer1.LoadDocument(new GrapeCity.ActiveReports.Document.PageDocument(pageReport));
        }
        else if (reportPathOrResource.EndsWith(".rpx", StringComparison.OrdinalIgnoreCase))
        {
            // Load RPX format
            using var xml = XmlReader.Create(reportStream);
            var sectionReport = new GrapeCity.ActiveReports.SectionReport();
            sectionReport.LoadLayout(xml);
            viewer1.LoadDocument(sectionReport);
        }
        else
        {
            throw new InvalidOperationException("Unknown report format.");
        }
    }
}

This approach checks the file extension and applies the appropriate loading mechanism for RDLX or RPX. By centralizing this logic, your form’s code stays clean – you simply call LoadReportIntoViewer("MyApp.Reports.InvoiceReport.rdlx", fromResource:true) for an embedded RDLX, or LoadReportIntoViewer(@"C:\Reports\Statement.rpx") for an external RPX, etc. The method handles the rest. 

(As an alternative, the viewer control provides an overload viewer1.LoadDocument(Stream, GrapeCity.Viewer.Common.DocumentFormat) that you can use to directly load a stream if you know the format, e.g., DocumentFormat.Rdlx or DocumentFormat.Section. The above method, however, makes the logic explicit and easy to maintain.)

Conclusion

By following the above steps, you should have the ActiveReports Viewer integrated into your .NET 9 WinForms app, allowing you to load RDLX reports and RPX section reports seamlessly. The viewer provides a rich set of features (navigation, export, print, parameter UI, etc.) out of the box, so once the report is loaded, end-users can interact with it immediately. Happy reporting!

 

Ready to check it out? Download ActiveReports.NET Today!

Tags: