ActiveReports 11
Custom Resource Locator
ActiveReports 11 > ActiveReports User Guide > Concepts > Page Report/RDL Report Concepts > Custom Resource Locator

Page reports and RDL reports can resolve resources from your file system using file paths, but sometimes resources are preserved in very specific sources, such as a database. With RDL report, you can create a custom resource locator to read any resources that might be required by your reports from any type of location. You can use it for resources such as images and theme files, or for reports to use in drillthrough links, subreports, or master reports.

API

You can implement a custom resource locator by deriving from the ResourceLocator Class and overriding the GetResource method.

The GetResource method returns ParentUri and Value properties. The Value property contains the located resource as a memory stream. The ParentUri property contains the string URI of the parent of the resource within the resource hierarchy.

Here is the GetResource method used in the sample.

C# MyPicturesLocator.cs code showing usage of the GetResource Method from the Sample

C# code. Paste inside a class.
Copy Code
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using GrapeCity.ActiveReports.Extensibility;
using GrapeCity.ActiveReports.Samples.CustomResourceLocator.Properties;
namespace GrapeCity.ActiveReports.Samples.CustomResourceLocator
{
    /// Implementation of ResourceLocator which looks for resources in the My Pictures folder.
    internal sealed class MyPicturesLocator : ResourceLocator
    {
        private const string UriSchemeMyImages = "MyPictures:";
        /// Obtains and returns the resource, or returns null if it is not found.
        public override Resource GetResource(ResourceInfo resourceInfo)
        {
            
            Resource resource;
            string name = resourceInfo.Name;
            if (name == null || name.Length == 0)
            {
                throw new ArgumentException(Resources.ResourceNameIsNull, "name");
            }
            Uri uri = new Uri(name);
            if (uri.GetLeftPart(UriPartial.Scheme).StartsWith(UriSchemeMyImages, true, CultureInfo.InvariantCulture))
            {
                Stream stream = GetPictureFromSpecialFolder(uri);
                if (stream == null)
                {
                    stream = new MemoryStream();
                    Resources.NoImage.Save(stream, Resources.NoImage.RawFormat);
                }
                resource = new Resource(stream, uri);
            }
            else
            {
                throw new InvalidOperationException(Resources.ResourceSchemeIsNotSupported);
            }
            return resource;
        }
        /// Returns a stream containing the specified image from the My Pictures folder, or null if the picture is not found. 
                /// The path parameter is the URI of the image located in My Pictures, e.g. MyImages:logo.gif
        private static Stream GetPictureFromSpecialFolder(Uri path)
        {
            int startPathPos = UriSchemeMyImages.Length;
            if (startPathPos >= path.ToString().Length)
            {
                return null;
            }
            string pictureName = path.ToString().Substring(startPathPos);
            string myPicturesPath = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
            if (!myPicturesPath.EndsWith("\\")) myPicturesPath += "\\";
             string picturePath = Path.Combine(myPicturesPath, pictureName);
            if (!File.Exists(picturePath)) return null;
            MemoryStream stream = new MemoryStream();
            try
            {
                Image picture = Image.FromFile(picturePath);
                picture.Save(stream, picture.RawFormat);
                stream.Position = 0;
            }
            catch(OutOfMemoryException) 
                        /// The file is not a valid image, or GDI+ doesn't support the image type.
            {
                return null;                            
            }
            catch(ExternalException) 
                        /// The image can't be saved.
            {
                return null;
            }
            return stream;
        }
    }
}

Visual Basic MyPicturesLocator.vb code showing usage of the GetResource Method from the Sample

Visual Basic code. Paste inside a class.
Copy Code
Imports GrapeCity.ActiveReports.Extensibility
Imports System.Globalization
Imports System.IO
Imports System.Runtime.InteropServices

Public Class MyPicturesLocator
    Inherits ResourceLocator

    Const UriSchemeMyImages As String = "MyPictures:"

    ' Obtains and returns the resource, or null if it is not found. 
        ' The resourceInfo parameter contains the information about the resource to obtain.
    
    Public Overrides Function GetResource(ByVal resourceInfo As ResourceInfo) As Resource
        Dim resource As Resource
        Dim name As String = resourceInfo.Name

        If (String.IsNullOrEmpty(name)) Then

            Throw New ArgumentException(My.Resources.ResourceNameIsNull, "name")

        End If

        Dim uri As New Uri(name)
        If (Uri.GetLeftPart(UriPartial.Scheme).StartsWith(UriSchemeMyImages, True, CultureInfo.InvariantCulture)) Then

            Dim stream As Stream = GetPictureFromSpecialFolder(uri)
            If (stream Is Nothing) Then
                stream = New MemoryStream()
                My.Resources.NoImage.Save(stream, My.Resources.NoImage.RawFormat)
            End If
            resource = New Resource(stream, uri)

        Else
            Throw New InvalidOperationException(My.Resources.ResourceSchemeIsNotSupported)
        End If
        Return resource
    End Function

    Function GetPictureFromSpecialFolder(ByVal path As Uri) As Stream
        Dim startPathPos As Integer = UriSchemeMyImages.Length

        If (startPathPos >= path.ToString().Length) Then
            Return Nothing
        End If

        Dim pictureName As String = path.ToString().Substring(startPathPos)
        Dim myPicturesPath As String = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)

        If (Not myPicturesPath.EndsWith("\\")) Then
            myPicturesPath += "\\"
        End If

        Dim picturePath As String = System.IO.Path.Combine(myPicturesPath, pictureName)

        If (Not File.Exists(picturePath)) Then
            Return Nothing
        End If

        Dim stream As New MemoryStream()

        Try
            Dim picture As Image = Image.FromFile(picturePath)
            picture.Save(stream, picture.RawFormat)
            stream.Position = 0
        Catch ex As OutOfMemoryException 
                ' The file is not a valid image, or GDI+ doesn't support the image type.
            Return Nothing
        Catch ex As ExternalException 
                ' The image can't be saved.
            Return Nothing
        End Try

        Return stream
    End Function

End Class

Sample

In the Samples folder installed with the product, there is a Custom Resource Locator sample in a path like:

C:\Users\MyUserName\Documents\GrapeCity Samples\ActiveReports 11\Page Reports\RDL\API\C#\CustomResourceLocator 

This sample contains a custom resource locator that looks for files in the current user’s My Pictures folder. It does this by looking for special MyPictures protocol.

See Also

Walkthroughs