Utilizzo degli oggetti DrawingVisual

In questo argomento viene fornita una panoramica di come usare DrawingVisual gli oggetti nel livello visivo WPF.

Oggetto DrawingVisual

DrawingVisual è una classe di disegno leggera utilizzata per eseguire il rendering di forme, immagini o testo. Questa classe è considerata semplice perché non offre la gestione di layout o eventi, con un conseguente aumento delle prestazioni. Per questo motivo, i disegni sono ideali per sfondi e ClipArt.

Contenitore host di DrawingVisual

Per usare DrawingVisual gli oggetti, è necessario creare un contenitore host per gli oggetti . L'oggetto contenitore host deve derivare dalla FrameworkElement classe , che fornisce il supporto per il layout e la gestione degli eventi mancanti nella DrawingVisual classe . Tramite l'oggetto contenitore host non vengono visualizzate proprietà visibili, poiché lo scopo principale di questo oggetto è quello di contenere oggetti figlio. Tuttavia, la Visibility proprietà del contenitore host deve essere impostata su Visible; in caso contrario, nessuno dei relativi elementi figlio sarà visibile.

Quando si crea un oggetto contenitore host per oggetti visivi, è necessario archiviare i riferimenti all'oggetto visivo in un oggetto VisualCollection. Usare il Add metodo per aggiungere un oggetto visivo al contenitore host. Nell'esempio seguente viene creato un oggetto contenitore host e al relativo VisualCollectionoggetto visivo vengono aggiunti tre oggetti visivi.

// 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

Nota

Per l'esempio di codice completo dal quale è stato estratto l'esempio di codice precedente, vedere Hit Test Using DrawingVisuals Sample (Esempio di Hit Test mediante DrawingVisual).

Creazione di oggetti DrawingVisual

Quando si crea un DrawingVisual oggetto, non ha contenuto di disegno. È possibile aggiungere contenuto di testo, grafica o immagine recuperando il contenuto dell'oggetto DrawingContext e disegnandolo. Un DrawingContext oggetto viene restituito chiamando il RenderOpen metodo di un DrawingVisual oggetto .

Per disegnare un rettangolo in DrawingContext, utilizzare il DrawRectangle metodo dell'oggetto DrawingContext . Sono disponibili metodi simili per disegnare altri tipi di contenuto. Al termine del disegno del contenuto in DrawingContext, chiamare il Close metodo per chiudere DrawingContext e rendere persistente il contenuto.

Nell'esempio seguente viene creato un DrawingVisual oggetto e viene disegnato un rettangolo nel relativo DrawingContextoggetto .

// 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

Creazione di override per i membri FrameworkElement

L'oggetto contenitore host è responsabile della gestione della raccolta di oggetti visivi. Ciò richiede che il contenitore host implementi gli override dei membri per la classe derivata FrameworkElement .

L'elenco seguente descrive due membri per i quali è necessario eseguire l'override:

  • GetVisualChild: restituisce un elemento figlio in corrispondenza dell'indice specificato dalla raccolta di elementi figlio.

  • VisualChildrenCount: ottiene il numero di elementi figlio visivi all'interno di questo elemento.

Nell'esempio seguente vengono implementate le sostituzioni per i due FrameworkElement membri.


// 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

Supporto per l'hit testing

L'oggetto contenitore host può fornire la gestione degli eventi anche se non visualizza proprietà visibili, ma la relativa Visibility proprietà deve essere impostata su Visible. Ciò consente di creare una routine di gestione degli eventi per il contenitore host in grado di intercettare eventi del mouse, ad esempio il rilascio del pulsante sinistro del mouse. La routine di gestione degli eventi può quindi implementare hit testing richiamando il HitTest metodo . Il parametro del HitTestResultCallback metodo fa riferimento a una procedura definita dall'utente che è possibile usare per determinare l'azione risultante di un hit test.

Nell'esempio seguente il supporto per l'hit testing viene implementato per l'oggetto contenitore host e i relativi elementi figlio.

// 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

Vedi anche