Using Microsoft ReportViewer with WPF

Sometimes Microsoft delivers new technologies that aren’t as polished as we would like. Using the MS ReportViewer in a WPF UI project is one of those times. The issue is the lack of a native WPF control for viewing SQL Server Reporting Services (SSRS) report files. As far as I am aware and as of the date of this blog post, there is still no native control released by MS. It is the purpose of this posting to walk through how to integrate the Winforms version of the ReportViewer control with a WPF project.

The SSRS package includes a ReportViewer component, which is used to host or display a report inside a Windows Forms control. As mentioned earlier, for reasons only known to MS, the control for WPF hasn’t been created yet. To display a report in WPF using the Windows Forms control we must run the control in a special host container that can proxy compatibility between Winforms and WPF.

The WindowsFormsHost control for WPF can be found in the “WindowsFormsIntegration.dll” assembly provided with .NET 4. Its purpose is to fully integrate and host a Windows Forms control in a WPF control. It can host any controls that derive from the System.Windows.Forms namespace. The downside of using this control is that we lose the ability to control the layout of the content in the designer because it doesn’t render until runtime. An alternative is to make a WinForms User Control and design it beforehand so you get the desired layout results at runtime.

To use the control, add the following references to the WPF application that will host the control:

  • System.Windows.Forms
  • WindowsFormsIntegration

In addition to the references, you will need to select the appropriate version of the ReportViewer control. v9.0 for SQL 2005 and v10.0 for SQL 2008.

Next we will need to set some base XAML. In this example, the control will take up the entire window.

<local:WindowBase x:Class="Pineywoods.Example.UI.Forms.ReportViewerForm"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:Pineywoods.Example.UI">
        <Grid x:Name="LayoutRoot"/>
</local:WindowBase>
									


Here is the code to go along with the form. We create the WindowsHostControl and add it as a child of LayoutRoot. The actual report is a child of the WindowsHostControl, which acts as the proxy.

try
{
    // Create instance of WindowsFormsHost to integrate the report viewer control with the WPF form. 
    WindowsFormsHost host = new WindowsFormsHost();

    // Create instance of Report Viewer Control 
    Microsoft.Reporting.WinForms.ReportViewer reportViewer = new Microsoft.Reporting.WinForms.ReportViewer();
    reportViewer.ProcessingMode = ProcessingMode.Remote;
    reportViewer.ServerReport.ReportServerUrl = new Uri("SSRS_SERVER_URL");
    reportViewer.ServerReport.ReportPath = "ITEM_PATH_HERE";

    // Set the Basic authentication credentials. (http://msdn.microsoft.com/en-US/library/microsoft.reporting.winforms.reportservercredentials.networkcredentials(v=VS.100).aspx)
    reportViewer.ServerReport.ReportServerCredentials.NetworkCredentials = new System.Net.NetworkCredential("JOE_USER", "SECRET", "");

    // Causes the current report in the Report Viewer to be processed and rendered. 
    reportViewer.RefreshReport();

    // Sets the child control hosted by the WindowsFormsHost element. 
    host.Child = reportViewer;

    // Add the WindowsFormsHost element to the Grid in the ReportViewer.xaml 
    LayoutRoot.Children.Add(host);
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}

									

Hope this quick post helps someone to avert the frustration we encountered when integrating the control for the first time.