Usar objetos DrawingVisual

En este tema se proporciona información general sobre cómo utilizar los objetos DrawingVisual en la capa visual de WPF.

Este tema contiene las secciones siguientes.

  • Objeto DrawingVisual

  • Contenedor host de DrawingVisual

  • Crear objetos DrawingVisual

  • Crear invalidaciones para miembros de FrameworkElement

  • Proporcionar compatibilidad con las pruebas de posicionamiento

  • Temas relacionados

Objeto DrawingVisual

DrawingVisual es una clase de dibujo ligera que se utiliza para representar formas, imágenes o texto. Esta clase se considera ligera porque no proporciona administración del diseño ni control de eventos, lo que mejora su rendimiento. Por esta razón, los dibujos son idóneos para fondos e imágenes prediseñadas.

Contenedor host de DrawingVisual

A fin de usar los objetos DrawingVisual, debe crear un contenedor host para ellos. El objeto contenedor host debe derivarse de la clase FrameworkElement, que proporciona el diseño y la compatibilidad con el control de eventos que la clase DrawingVisual no tiene. El objeto contenedor host no muestra ninguna propiedad visible, puesto que su finalidad principal es contener objetos secundarios. Sin embargo, la propiedad Visibility del contenedor host debe estar establecida en Visible; de lo contrario, ninguno de sus elementos secundarios estará visible.

Cuando se crea un objeto contenedor host para objetos visuales, es preciso almacenar las referencias a objeto visuales en VisualCollection. Utilice el método Add para agregar un objeto visual al contenedor host. En el ejemplo siguiente, se crea un objeto contenedor host y se agregan tres objetos visuales a su colección VisualCollection.

    ' Create a host visual derived from the FrameworkElement class.
    ' This class provides layout, event handling, and container support for
    ' the child visual objects.
    Public Class MyVisualHost
        Inherits FrameworkElement
        ' Create a collection of child visual objects.
        Private _children As VisualCollection

        Public Sub New()
            _children = New VisualCollection(Me)
            _children.Add(CreateDrawingVisualRectangle())
            _children.Add(CreateDrawingVisualText())
            _children.Add(CreateDrawingVisualEllipses())

            ' Add the event handler for MouseLeftButtonUp.
            AddHandler MouseLeftButtonUp, AddressOf MyVisualHost_MouseLeftButtonUp
        End Sub
// Create a host visual derived from the FrameworkElement class.
// This class provides layout, event handling, and container support for
// the child visual objects.
public class MyVisualHost : FrameworkElement
{
    // Create a collection of child visual objects.
    private VisualCollection _children;

    public MyVisualHost()
    {
        _children = new VisualCollection(this);
        _children.Add(CreateDrawingVisualRectangle());
        _children.Add(CreateDrawingVisualText());
        _children.Add(CreateDrawingVisualEllipses());

        // Add the event handler for MouseLeftButtonUp.
        this.MouseLeftButtonUp += new System.Windows.Input.MouseButtonEventHandler(MyVisualHost_MouseLeftButtonUp);
    }
NotaNota

Para obtener el ejemplo de código completo del que se ha extraído el ejemplo de código anterior, vea Hit Test Using DrawingVisuals Sample.

Crear objetos DrawingVisual

Al crear un objeto DrawingVisual, no tiene contenido de dibujo. Puede agregar contenidos de texto, gráficos o imágenes recuperando el objeto DrawingContext del objeto y dibujando en él. Para devolver un contexto de dibujo (DrawingContext), se llama al método RenderOpen de un objeto DrawingVisual.

Para dibujar un rectángulo en DrawingContext, utilice el método DrawRectangle del objeto DrawingContext. Existen métodos similares para dibujar otros tipos de contenido. Cuando haya terminado de dibujar contenido en DrawingContext, llame al método Close para cerrar el DrawingContext y conservar el contenido.

En el ejemplo siguiente, se crea un objeto DrawingVisual y se dibuja un rectángulo en DrawingContext.

        ' Create a DrawingVisual that contains a rectangle.
        Private Function CreateDrawingVisualRectangle() As DrawingVisual
            Dim drawingVisual As New DrawingVisual()

            ' Retrieve the DrawingContext in order to create new drawing content.
            Dim drawingContext As DrawingContext = drawingVisual.RenderOpen()

            ' Create a rectangle and draw it in the DrawingContext.
            Dim rect As New Rect(New Point(160, 100), New Size(320, 80))
            drawingContext.DrawRectangle(Brushes.LightBlue, CType(Nothing, Pen), rect)

            ' Persist the drawing content.
            drawingContext.Close()

            Return drawingVisual
        End Function
// Create a DrawingVisual that contains a rectangle.
private DrawingVisual CreateDrawingVisualRectangle()
{
    DrawingVisual drawingVisual = new DrawingVisual();

    // Retrieve the DrawingContext in order to create new drawing content.
    DrawingContext drawingContext = drawingVisual.RenderOpen();

    // Create a rectangle and draw it in the DrawingContext.
    Rect rect = new Rect(new System.Windows.Point(160, 100), new System.Windows.Size(320, 80));
    drawingContext.DrawRectangle(System.Windows.Media.Brushes.LightBlue, (System.Windows.Media.Pen)null, rect);

    // Persist the drawing content.
    drawingContext.Close();

    return drawingVisual;
}

Crear invalidaciones para miembros de FrameworkElement

El objeto contenedor host es responsable de administrar su colección de objetos visuales. Para ello, el contenedor host debe implementar invalidaciones de miembros para la clase FrameworkElement derivada.

En la lista siguiente se describen los dos miembros que se deben invalidar:

  • GetVisualChild: devuelve un elemento secundario en el índice especificado de la colección de elementos secundarios.

  • VisualChildrenCount: obtiene el número de elementos secundarios visuales de este elemento.

En el ejemplo siguiente, se implementan invalidaciones para los dos miembros de FrameworkElement.


        ' Provide a required override for the VisualChildrenCount property.
        Protected Overrides ReadOnly Property VisualChildrenCount() As Integer
            Get
                Return _children.Count
            End Get
        End Property

        ' Provide a required override for the GetVisualChild method.
        Protected Overrides Function GetVisualChild(ByVal index As Integer) As Visual
            If index < 0 OrElse index >= _children.Count Then
                Throw New ArgumentOutOfRangeException()
            End If

            Return _children(index)
        End Function


        // Provide a required override for the VisualChildrenCount property.
        protected override int VisualChildrenCount
        {
            get { return _children.Count; }
        }

        // Provide a required override for the GetVisualChild method.
        protected override Visual GetVisualChild(int index)
        {
            if (index < 0 || index >= _children.Count)
            {
                throw new ArgumentOutOfRangeException();
            }

            return _children[index];
        }

Proporcionar compatibilidad con las pruebas de posicionamiento

El objeto contenedor host puede proporcionar control de eventos aunque no muestre ninguna propiedad visible. Sin embargo, su propiedad Visibility debe estar establecida en Visible. Esto permite crear una rutina de control de eventos para el contenedor host capaz de interceptar los eventos del mouse, tales como soltar el botón primario. A continuación, la rutina de control de eventos puede implementar pruebas de posicionamiento invocando el método HitTest. El parámetro HitTestResultCallback del método hace referencia a un procedimiento definido por el usuario que puede utilizar para determinar la acción resultante de una prueba de posicionamiento.

En el ejemplo siguiente, se implementa la compatibilidad con las pruebas de posicionamiento del objeto contenedor host y sus elementos secundarios.

        ' Capture the mouse event and hit test the coordinate point value against
        ' the child visual objects.
        Private Sub MyVisualHost_MouseLeftButtonUp(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
            ' Retreive the coordinates of the mouse button event.
            Dim pt As Point = e.GetPosition(CType(sender, UIElement))

            ' Initiate the hit test by setting up a hit test result callback method.
            VisualTreeHelper.HitTest(Me, Nothing, New HitTestResultCallback(AddressOf myCallback), New PointHitTestParameters(pt))
        End Sub

        ' If a child visual object is hit, toggle its opacity to visually indicate a hit.
        Public Function myCallback(ByVal result As HitTestResult) As HitTestResultBehavior
            If result.VisualHit.GetType() Is GetType(DrawingVisual) Then
                If (CType(result.VisualHit, DrawingVisual)).Opacity = 1.0 Then
                    CType(result.VisualHit, DrawingVisual).Opacity = 0.4
                Else
                    CType(result.VisualHit, DrawingVisual).Opacity = 1.0
                End If
            End If

            ' Stop the hit test enumeration of objects in the visual tree.
            Return HitTestResultBehavior.Stop
        End Function
// Capture the mouse event and hit test the coordinate point value against
// the child visual objects.
void MyVisualHost_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    // Retreive the coordinates of the mouse button event.
    System.Windows.Point pt = e.GetPosition((UIElement)sender);

    // Initiate the hit test by setting up a hit test result callback method.
    VisualTreeHelper.HitTest(this, null, new HitTestResultCallback(myCallback), new PointHitTestParameters(pt));
}

// If a child visual object is hit, toggle its opacity to visually indicate a hit.
public HitTestResultBehavior myCallback(HitTestResult result)
{
    if (result.VisualHit.GetType() == typeof(DrawingVisual))
    {
        if (((DrawingVisual)result.VisualHit).Opacity == 1.0)
        {
            ((DrawingVisual)result.VisualHit).Opacity = 0.4;
        }
        else
        {
            ((DrawingVisual)result.VisualHit).Opacity = 1.0;
        }
    }

    // Stop the hit test enumeration of objects in the visual tree.
    return HitTestResultBehavior.Stop;
}

Vea también

Referencia

DrawingVisual

HitTest

Conceptos

Información general sobre la representación de gráficos en WPF

Realizar pruebas de posicionamiento en la capa visual