Verwenden von DrawingVisual-Objekten

Dieses Thema bietet einen Überblick über die Verwendung von DrawingVisual-Objekten in der visuellen Ebene von WPF.

DrawingVisual-Objekt

Die DrawingVisual ist eine einfache Zeichnungsklasse, die zum Rendern von Formen, Bildern oder Text verwendet wird. Diese Klasse wird als einfach angesehen, weil sie weder Layout noch Ereignisbehandlung bereitstellt. Dadurch wird die Leistung gesteigert. Aus diesem Grund sind Zeichnungen ideal für Hintergründe und ClipArt.For this reason, drawings are ideal for backgrounds and clipart.

DrawingVisual-Hostcontainer

Um DrawingVisual Objekte verwenden zu können, müssen Sie einen Hostcontainer für die Objekte erstellen. Das Hostcontainerobjekt muss von der FrameworkElement-Klasse abgeleitet werden, die die Layout- und Ereignisbehandlung unterstützt, welche der DrawingVisual-Klasse fehlt. Das Hostcontainerobjekt zeigt keine sichtbaren Eigenschaften, da seine Hauptfunktion die Aufnahme untergeordneter Objekte ist. Allerdings muss die Visibility-Eigenschaft des Hostcontainers auf Visible gesetzt werden, da sonst keines der untergeordneten Elemente sichtbar ist.

Wenn Sie ein Hostcontainerobjekt für visuelle Objekte erstellen, müssen Sie die Verweise von visuellen Objekten in einer VisualCollection speichern. Verwenden Sie die Add-Methode, um dem Hostcontainer ein visuelles Objekt hinzuzufügen. Im folgenden Beispiel wird ein Hostcontainerobjekt erstellt, und seiner VisualCollection werden drei visuelle Objekte hinzugefügt.

// 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);
    }
' 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

Anmerkung

Informationen über das vollständige Codebeispiel, aus dem das vorherige Codebeispiel extrahiert wurde, finden Sie unter Beispiel für Treffertests mit DrawingVisuals.

Erstellen von DrawingVisual-Objekten

Wenn Sie ein DrawingVisual-Objekt erstellen, enthält es keinen Zeichnungsinhalt. Sie können Text, Grafiken oder Bildinhalte hinzufügen, indem Sie die DrawingContext des Objekts abrufen und darin zeichnen. Ein DrawingContext wird zurückgegeben, indem die RenderOpen-Methode eines DrawingVisual-Objekts aufgerufen wird.

Verwenden Sie die DrawRectangle-Methode des DrawingContext-Objekts, um ein Rechteck in das DrawingContextzu zeichnen. Ähnliche Methoden sind zum Zeichnen anderer Inhaltstypen vorhanden. Wenn Sie das Zeichnen von Inhalten in DrawingContext abgeschlossen haben, rufen Sie die Close-Methode auf, um den DrawingContext zu schließen und den Inhalt beizubehalten.

Im folgenden Beispiel wird ein DrawingVisual-Objekt erstellt und in dessen DrawingContext ein Rechteck gezeichnet.

// 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;
}
' 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

Erstellen von Überschreibungen für Elemente von FrameworkElement

Das Host-Container-Objekt ist für die Verwaltung seiner Sammlung visueller Objekte verantwortlich. Dies erfordert, dass der Hostcontainer Elementüberschreibungen für die abgeleitete FrameworkElement-Klasse implementiert.

Die folgende Liste beschreibt die zwei Elemente, die Sie überschreiben müssen:

  • GetVisualChild: Gibt aus einer Sammlung untergeordneter Elemente ein untergeordnetes Element an der angegebenen Indexposition zurück

  • VisualChildrenCount: Ruft die Anzahl der untergeordneten visuellen Elemente innerhalb dieses Elements ab

Im folgenden Beispiel werden Überschreibungen für die beiden FrameworkElement-Member implementiert.


// 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];
}


' 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

Bereitstellen von Unterstützung für den Treffertest

Das Hostcontainerobjekt kann die Ereignisbehandlung bereitstellen, auch wenn keine sichtbaren Eigenschaften angezeigt werden. Die Visibility-Eigenschaft muss jedoch auf Visiblefestgelegt werden. Auf diese Weise können Sie eine Ereignisbehandlungsroutine für den Hostcontainer erstellen, die Mausereignisse abfangen kann, z. B. die Freigabe der linken Maustaste. Die Ereignisbehandlungsroutine kann dann Hit-Testing implementieren, indem sie die Methode HitTest aufruft. Der HitTestResultCallback-Parameter der Methode bezieht sich auf eine benutzerdefinierte Prozedur, die Sie verwenden können, um die resultierende Aktion eines Treffertests zu bestimmen.

Im folgenden Beispiel wird die Unterstützung für Treffertests für das Hostcontainerobjekt und seine untergeordneten Elemente implementiert.

// 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)
{
    // Retrieve 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;
}
' 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)
    ' Retrieve 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

Weitere Informationen