Search code examples
c#reporting-servicesrdlcembedded-resource

How to share and embedded image on many RDLC Reports


I created an MDI application that shows some DataGridViews on different child Forms that are considered as separate application because they have access to different databases.

Those data need to be exported in PDF reports. I used the ReportViewer component inside a new MDI child form and I created a new Project on the solution that contains only the RDLC report files as embedded resources, associated to each application. This was done to avoid having an user accessible folder inside the program folder that contains each .RDLC file, for security reasons.

This is the files/folders structure of the VS Solution:

Solution
|
|_ Classes
| |
| |_ Library Project that contains all the classes used for Data Access...
|
|_ MDIMain
| |
| |_ The main application Project that contains some Core Classes and Forms...
|
|_ Reports (A DLL project that doesn't contain .cs code files, but only folders and RDLC reports)
  |
  |_ App1
  | |
  | |_ Report1.rdlc
  | |_ Report2.rdlc
  | |_ ...
  |
  |_ App2
    |
    |_ Report1.rdlc
    |_ ...

All works fine, but now I need to customize all my reports by inserting a logo, so an Image. So I need to add to every report the same image.

Looking on MSDN documentation it seems that there're 3 kind of possible source for images:

  • "Embedded": works only by embedding the image inside the single report file. But in my case this is not a valid soluition due to waste of storage.
  • "External": by specifing URL or path (what I'd like to do).
  • "Database": specify the database field that contains the image.

The .rdlc files are referred and loaded inside the ReportViewer windows, by using the Reports.dll library as source using a "folder.filename" syntax.

/* 
 * reportSource variable is calculated dynamically with the selection on a ComboBox
 * that let the use choose a specific report.
 * The source format is like this: "Reports.AppNameFolder.Report1.rdlc"
 */

string reportSource = cmbReport.SelectedValue.ToString();
ReportDataSource rds = new ReportDataSource("");
rds.Name = "DataSet";
rds.Value = _reportDataTable;

Assembly assembly = Assembly.LoadFrom("Reports.dll");
UnmanagedMemoryStream reportStream = (UnmanagedMemoryStream)assembly.GetManifestResourceStream(reportSource);

reportViewer1.LocalReport.DataSources.Clear();
reportViewer1.LocalReport.LoadReportDefinition(reportStream);
reportViewer1.LocalReport.DataSources.Add(rds);
reportViewer1.RefreshReport();

So, if I want to create a folder that contains my images:

  1. Where should I put it, with the certainty that then the folder is generated together with the output of the main project?
  2. How can I do to keep the reference to the folder and images both in debug mode, and release mode, so when the program will be installed in the user client?

Solution

  • You can do the following

    in the image properties on the report

    1. Image Source : Embedded
    2. click import button and load the image

    in this way, the RDLC will save the image as base64 inside of the file rdlc, you can view by open with xml editor from the solution explorer pane, and no need to worry about the location of the image.

    another way if you want to load the image from the database for example, you can do the following

    1. Image Source: Database
    2. Use this field: [YourPropertyName]
    3. Use this MIME type: image/jpeg
    4. in the report dataset, add a byte[] column or property called YourPropertyName

    Last Note, if the logo is common in all the reports you have, its recommended to add subreport called header that contains this logo and you put it in each report you have, this way if you want to change the logo later, you only need to change it in that header subreport.

    you can view this demo I prepared to show you how to achieve this ( to add a header report to your current report)

    hope this will help you