Crear un componente de tiempo de ejecución de elemento de informe personalizado

El componente de tiempo de ejecución del elemento de informe personalizado se implementa como un componente Microsoft .NET Framework utilizando cualquier lenguaje compatible con CLS y el procesador del informe lo llama en el tiempo de ejecución. Las propiedades para el componente de tiempo de ejecución en el entorno de diseño se definen modificando el componente de tiempo de diseño correspondiente del elemento de informe personalizado.

Para obtener una muestra de un elemento de informe personalizado implementado totalmente, vea Muestras de productos de SQL Server Reporting Services.

Objetos de definición e instancia

Antes de implementar un elemento de informe personalizado, es importante entender la diferencia entre los objetos de definición y objetos de instancia. Los objetos de definición proporcionan la representación RDL del elemento de informe personalizado mientras que objetos de instancia son las versiones evaluadas de los objetos de definición. Hay solo un objeto de definición para cada elemento en el informe. Al tener acceso a las propiedades en un objeto de definición que contiene expresiones, obtendrá una cadena de expresión no evaluada. Los objetos de instancia contienen las versiones evaluadas de los objetos de definición y pueden tener una relación uno a varios con el objeto de definición de un elemento. Por ejemplo, si un informe tiene una región de datos Tablix que contiene un CustomReportItem en una fila de detalle, solo habrá un objeto de definición, pero habrá un objeto de instancia para cada fila en la región de datos.

Implementar la interfaz ICustomReportItem

Para crear un componente de tiempo de ejecución CustomReportItem, necesitará implementar la interfaz ICustomReportItem que se define en Microsoft.ReportingServices.ProcessingCore.dll:

namespace Microsoft.ReportingServices.OnDemandReportRendering
{
    public interface ICustomReportItem
    {
        void GenerateReportItemDefinition(CustomReportItem customReportItem);
void EvaluateReportItemInstance(CustomReportItem customReportItem);
    }
}

Después de haber implementado la interfaz ICustomReportItem, se generarán dos códigos auxiliares de método: GenerateReportItemDefinition y EvaluateReportItemInstance. El método GenerateReportItemDefinition se llama primero y se utiliza para establecer las propiedades de definición y crear el objeto Image que contendrá las propiedades de instancia y definición que se utilizan para representar el elemento. Se llama al método EvaluateReportItemInstance una vez evaluados los objetos de definición, y este método proporciona los objetos de instancia que se utilizarán para representar el elemento.

La siguiente es una implementación de ejemplo de un elemento de informe personalizado que representa el nombre del control como una imagen.

namespace Microsoft.Samples.ReportingServices
{
    using System;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Drawing.Imaging;
    using System.IO;
    using System.Text;
    using Microsoft.ReportingServices.OnDemandReportRendering;

    public class PolygonsCustomReportItem : ICustomReportItem
    {
        #region ICustomReportItem Members

        public void GenerateReportItemDefinition(CustomReportItem cri)
        {
            // Create the Image object that will be 
            // used to render the custom report item
            cri.CreateCriImageDefinition();
            Image polygonImage = (Image)cri.GeneratedReportItem;
        }

        public void EvaluateReportItemInstance(CustomReportItem cri)
        {
            // Get the Image definition
            Image polygonImage = (Image)cri.GeneratedReportItem;

            // Create the image for the custom report item
            polygonImage.ImageInstance.ImageData = DrawImage(cri);
        }

        #endregion

        /// <summary>
        /// Creates an image of the CustomReportItem's name
        /// </summary>
        private byte[] DrawImage(CustomReportItem customReportItem)
        {
            int width = 1;          // pixels
            int height = 1;         // pixels
            int resolution = 75;    // dpi

            System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(width, height);
            bitmap.SetResolution(resolution, resolution);

            System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(bitmap);
            graphics.PageUnit = System.Drawing.GraphicsUnit.Pixel;

            // Get the Font for the Text
            System.Drawing.Font font = new System.Drawing.Font(System.Drawing.FontFamily.GenericMonospace,
                12, System.Drawing.FontStyle.Regular);

            // Get the Brush for drawing the Text
            System.Drawing.Brush brush = new System.Drawing.SolidBrush(System.Drawing.Color.LightGreen);

            // Get the measurements for the image
            System.Drawing.SizeF maxStringSize = graphics.MeasureString(customReportItem.Name, font);
            width = (int)(maxStringSize.Width + 2 * font.GetHeight(resolution));
            height = (int)(maxStringSize.Height + 2 * font.GetHeight(resolution));

            bitmap.Dispose();
            bitmap = new System.Drawing.Bitmap(width, height);
            bitmap.SetResolution(resolution, resolution);

            graphics.Dispose();
            graphics = System.Drawing.Graphics.FromImage(bitmap);
            graphics.PageUnit = System.Drawing.GraphicsUnit.Pixel;
            
            // Draw the text
            graphics.DrawString(customReportItem.Name, font, brush, font.GetHeight(resolution), 
                font.GetHeight(resolution));

            // Create the byte array of the image data
            MemoryStream memoryStream = new MemoryStream();
            bitmap.Save(memoryStream, ImageFormat.Bmp);
            memoryStream.Position = 0;
            byte[] imageData = new byte[memoryStream.Length];
            memoryStream.Read(imageData, 0, imageData.Length);

            return imageData;
        }
    }
}