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 componente Microsoft .NET Framework con cualquier lenguaje compatible con CLS y el procesador del informe lo llama en tiempo de ejecución. Defina las propiedades para el componente de tiempo de ejecución en el entorno de diseño modificando el componente de tiempo de diseño correspondiente del elemento de informe personalizado.

Para obtener más información sobre un ejemplo de un elemento de informe personalizado implementado totalmente, vea Ejemplos de SQL Server Reporting Services.

Objetos de definición y de instancia

Antes de implementar un elemento de informe personalizado es importante entender la diferencia entre los objetos de definición y los objetos de instancias. 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 sólo uno 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 CustomReportItem en una fila de detalle, sólo 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 ImageDefinition 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 Definition 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;
        }
    }
}