Subreports help in splitting a report into multiple parts and allow us to control the amount of information a page can contain.
In my previous post, I wrote about creating an RDLC report using C# and WPF. You can check it out through this link.
In this article, I will be creating a project that uses SubReport to display the information of employees based on the department of each employee.
- Create a new WPF project called SubReportDemo.
- Create a new class called Employee and add the following code to it.
- namespace SubreportDemo
- {
- public class Employee
- {
- public int ID { get; set; }
- public string Name { get; set; }
- public string Email { get; set; }
- public string Gender { get; set; }
- }
- }
- Create another class called Department and add the following code to it.
- namespace SubreportDemo
- {
- public class Department
- {
- public string Name { get; set; }
- public int ID { get; set; }
- }
- }
- Rebuild the project.
- Add a new report item and name it MainReport.RDLC. Drag and drop a table into the report and set the data source to the Department model. Name the dataset "Department_DS".
- Design the table as shown below. Map the Name property to the Department column and add a SubReport to the Employees column.
- Right-click on the Subreport and select Properties. Set the Subreport name as EmployeeDetails, as shown below.
Go to Parameters and set the Name field as ID and select the ID from the dropdown in the Value field.
- Add another report file and name it Rdlc. This is the file that will be used as the Subreport. Always make sure that the name of the Subreport is same as the FileName of the Subreport without the rdlc extension.
- Add a table to the rdlc file, select the Employee Model as Datasource, and set the name of the dataset as Employee_DS.
Map the columns of the table to the corresponding properties of the dataset.
- Right-click on Parameters from the "Report Data Tool" window, add a parameter, and set its name as ID.
The name should always be the same as the name of parameter given to the Subreport initially.
ID is an int type so set the Datatype as Integer.
- Create a class called SubReportDemoViewModel.cs and add the below code to it.
- using Microsoft.Reporting.WinForms;
- using System;
- using System.Collections.Generic;
- using System.IO;
- namespace SubreportDemo
- {
- public class SubReportDemoViewModel
- {
- private MainWindow _mainWindow;
- private ReportViewer _reportViewer;
- public SubReportDemoViewModel(MainWindow window)
- {
- _mainWindow = window;
- _reportViewer = window.reportViewer;
- Initialize();
-
- }
-
- private IEnumerable<Department> departments = new List<Department>()
- {
- new Department() {ID = 1, Name = "Applied Mathematics" },
- new Department() {ID = 2, Name = "Software" },
- new Department() {ID = 3, Name = "Machine Learning" },
- new Department() {ID = 4, Name = "Petroleum Engineering" },
- };
- private void Initialize()
- {
- _reportViewer.LocalReport.DataSources.Clear();
- var departmentsModels = new ReportDataSource() { Name = "Department_DS", Value = departments };
- _reportViewer.LocalReport.DataSources.Add(departmentsModels);
- var path = Path.GetDirectoryName(Path.GetDirectoryName
- (Path.GetDirectoryName(Directory.GetCurrentDirectory())));
- var MainPage = path + @"\subreportDemo\MainReport.rdlc";
- _reportViewer.LocalReport.ReportPath = MainPage;
- _reportViewer.LocalReport.SubreportProcessing += LocalReport_SubreportProcessing;
- _reportViewer.LocalReport.EnableExternalImages = true;
- _reportViewer.SetDisplayMode(DisplayMode.PrintLayout);
- _reportViewer.Refresh();
- _reportViewer.RefreshReport();
-
- }
- private List<Employee> Employees = new List<Employee>()
- {
- new Employee() {ID = 1, Name = "Sam", Gender ="male", Email="[email protected]"},
- new Employee() {ID = 1, Name = "Ella",Gender ="female", Email="[email protected]" },
- new Employee() {ID = 1, Name = "TG",Gender ="male", Email ="[email protected]" },
- new Employee() {ID = 1, Name = "Favor",Gender ="female", Email="[email protected]" },
- new Employee() {ID = 2,Name = "Micheal",Gender ="male",Email ="[email protected]" },
- new Employee() {ID = 2, Name = "Joe",Gender ="male", Email ="[email protected]" },
- new Employee() {ID = 2, Name="Maintain",Gender ="female",Email ="[email protected]" },
- new Employee() {ID = 3, Name = "Akeem",Gender ="male", Email ="[email protected]" },
- new Employee() {ID = 3, Name = "Boye",Gender ="male", Email ="[email protected]" },
- new Employee() {ID = 4, Name ="Chioma",Gender ="female",Email ="[email protected]" },
- new Employee() {ID = 4, Name = "Ofure",Gender ="female", Email ="[email protected]" },
- new Employee() {ID = 4, Name = "Hart",Gender ="male",Email ="[email protected]" }
- };
- private void LocalReport_SubreportProcessing(object sender, SubreportProcessingEventArgs e)
- {
- var ID = Convert.ToInt32(e.Parameters[0].Values[0]);
- var employeegroup = Employees.FindAll(x => x.ID == ID);
- if (e.ReportPath == "EmployeeDetails")
- {
- var employeeDetails = new ReportDataSource() { Name = "Employee_DS", Value = employeegroup };
- e.DataSources.Add(employeeDetails);
- }
- }
- }
- }
The reportViewer.LocalReport.SubreportProcessing event is triggered whenever a Subreport is found on a page and the method that subscribes to the event checks the Subreport path and uses ID which was set as the parameter to filter the information to display.
- Add this code the the mainWindow.xaml file.
- <Window x:Class="SubreportDemo.MainWindow"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:local="clr-namespace:SubreportDemo"
- mc:Ignorable="d"
- xmlns:rdlc="clr- namespace:Microsoft.Reporting.WinForms;assembly=Microsoft.ReportViewer.WinForms"
- Title="MainWindow" Height="350" Width="525">
- <Grid>
- <WindowsFormsHost >
- <rdlc:ReportViewer x:Name="reportViewer"/>
- </WindowsFormsHost>
- </Grid>
- </Window>
- Finally, add these to the MainWindow.xaml.cs file.
- using System.Windows;
-
- namespace SubreportDemo
- {
-
-
-
- public partial class MainWindow : Window
- {
- public MainWindow()
- {
- InitializeComponent();
- DataContext = new SubReportDemoViewModel(this);
- }
- }
- }
- Run the application