Leveraging the ReportViewer control in WPF

Microsoft's ReportViewer control is an ideal candidate for embedding reports in a WinForms application. It takes care of the generation, rendering, printing, and saving of reports, even if you don't host these in SQL Server Reporting Services. The ReportViewer only exists for WinForms and ASP.NET: there is no ReportViewer control for WPF. If you migrate a WinForms application to WPF, you can however leverage your existing reports and skills.

Any Win32 Control can be embeded in a WPF form by hosting it in a WindowsFormsHost element. All you need to do is add a reference in your project to Microsoft.ReportViewer.WinForms, and wrap the ReportViewer control in a WindowsFormsHost element, like this:

<Window x:Class="ReportViewerSample.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:rep="clr-namespace:Microsoft.Reporting.WinForms;assembly=Microsoft.ReportViewer.WinForms"
        Title="ReportViewer Sample" Height="800" Width="500">
    <DockPanel>
        <WindowsFormsHost x:Name="windowsFormsHost1">
            <rep:ReportViewer x:Name="ReportViewer1"></rep:ReportViewer>
        </WindowsFormsHost>
    </DockPanel>
</Window>


Unfortunately Visual Studio's designers and code generators won't help you in hooking up the datasets, the resources, and the report itself to the ReportViewer, so you have to do it all programmatically. Here's how your code could look like:

// Create and Fill DataSet(s)
AdventureWorksDataSet ads = new AdventureWorksDataSet();
SalesOrderDetailTableAdapter adapter = new SalesOrderDetailTableAdapter();
adapter.Fill(ads.SalesOrderDetail);
 
// Attach DataSource(s) to ReportViewer
ReportDataSource rds = new ReportDataSource();
rds.Name = "AdventureWorksDataSet_SalesOrderDetail";
rds.Value = ads.SalesOrderDetail; // Could also come from a WCF Service
ReportViewer1.LocalReport.DataSources.Add(rds);
 
// Attach Report to ReportViewer
ReportViewer1.LocalReport.ReportEmbeddedResource = "ReportViewerSample.SalesReport.rdlc";
// Alternative: ReportViewer1.LocalReport.ReportPath = @"../../SalesReport.rdlc";
 
// Populate Parameters
List<ReportParameter> parms = new List<ReportParameter>();
parms.Add(new ReportParameter("Report_Parameter_0", "25"));
ReportViewer1.LocalReport.SetParameters(parms);
 
// Display
ReportViewer1.RefreshReport();


8 comments:

  1. When i want to ReportViewer1.LocalReport.SetParameters(parms);
    it cause exception like this:
    Cannot create instance of ' ' defined in assembly ' Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Exception has been thrown by the target of an invocation. Error in markup file 'Wizards/Print.xaml' Line 1 Position 9."
    is there any solution for this?

    ReplyDelete
  2. you saved my life hehehheeh
    thank you

    ReplyDelete
  3. Know of any plans for a native WPF report viewer? We currently use WinFormsHost but it causes havoc on the display of our other controls for various reasons (Can't move other controls over the top of it, no hardware acceleration, etc.)?

    ReplyDelete
  4. Below is the code i am trying make use of for displaying a report in WPF Window.

    With WindowsFormsHost and report viewer control.

    Problem : it just displays a Blank Window. it gives No Errors, No messages.

    Just displays a blank window. please help.



    XAML Code




    Code Behind
    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
    try
    {
    List paramList = new List();
    paramList.Add(new ReportParameter("param1","16699"));
    reportViewer.ProcessingMode = ProcessingMode.Remote;
    reportViewer.ServerReport.ReportServerUrl = new Uri("http://server/reportserver");
    reportViewer.ServerReport.ReportPath = "/folder1/folder2/reportname";
    reportViewer.ServerReport.SetParameters(paramList);
    reportViewer.RefreshReport();
    reportViewer.Show();
    }
    catch (Exception ex)
    {
    MessageBox.Show(ex.Message);
    }

    ReplyDelete
  5. Hi Diederik!

    Thanks a lot for this code. I had the same requirement, and used your code for embedding a report viewer in the form. However, when i click on the button to view the report, it doesn't reflect anything, nor does it throw any runtime errors.

    Could you help me with some inputs that i need to look at? I tried creating a simple win form app and pointed the report in the report viewer of the same, and it worked. Thus, i know that there is no issue with the report, since this works independently fine.

    ReplyDelete
  6. Hi Again, Diederik! It was a silly mistake, I was using the wrong refresh() function. When I used RefreshReport(), it worked!

    ReplyDelete
  7. // Attach Report to ReportViewer

    ReportViewer1.LocalReport.ReportEmbeddedResource = "ReportViewerSample.SalesReport.rdlc";

    // Alternative: ReportViewer1.LocalReport.ReportPath = @"../../SalesReport.rdlc";

    these lines are not working

    pls help

    ReplyDelete