Użycie obiektów DrawingVisual

Ten temat zawiera omówienie sposobu używania DrawingVisual obiektów w warstwie wizualnej WPF.

RysunekVisual, obiekt

Jest DrawingVisual to uproszczona klasa rysunku używana do renderowania kształtów, obrazów lub tekstu. Ta klasa jest uważana za uproszczoną, ponieważ nie zapewnia układu ani obsługi zdarzeń, co poprawia jego wydajność. Z tego powodu rysunki są idealne dla tła i klipartu.

RysunekVisual Host Container

Aby używać DrawingVisual obiektów, należy utworzyć kontener hosta dla obiektów. Obiekt kontenera hosta musi pochodzić z FrameworkElement klasy, która zapewnia układ i obsługę zdarzeń, których brakuje w DrawingVisual klasie. Obiekt kontenera hosta nie wyświetla żadnych widocznych właściwości, ponieważ jego głównym celem jest zawieranie obiektów podrzędnych. Visibility Jednak właściwość kontenera hostów musi być ustawiona na Visible; w przeciwnym razie żadna z jego elementów podrzędnych nie będzie widoczna.

Podczas tworzenia obiektu kontenera hosta dla obiektów wizualnych należy przechowywać odwołania do obiektów wizualnych w obiekcie VisualCollection. Add Użyj metody , aby dodać obiekt wizualny do kontenera hostów. W poniższym przykładzie tworzony jest obiekt kontenera hosta, a do jego VisualCollectionobiektu są dodawane trzy obiekty wizualne.

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

Uwaga

Kompletny przykładowy kod, z którego wyodrębniono poprzedni przykład kodu, zobacz Hit Test using DrawingVisuals Sample (Test trafienia przy użyciu przykładu DrawingVisuals).

Tworzenie obiektów DrawingVisual

Podczas tworzenia DrawingVisual obiektu nie ma zawartości rysunku. Możesz dodać zawartość tekstu, grafiki lub obrazu, pobierając obiekty i rysując DrawingContext je. Obiekt jest DrawingContext zwracany przez wywołanie RenderOpen metody DrawingVisual obiektu.

Aby narysować prostokąt w obiekcie DrawingContext, użyj DrawRectangle metody DrawingContext obiektu . Podobne metody istnieją do rysowania innych typów zawartości. Po zakończeniu DrawingContextrysowania zawartości do metody wywołaj metodę Close , aby zamknąć DrawingContext i utrwały zawartość.

W poniższym przykładzie DrawingVisual tworzony jest obiekt, a prostokąt jest rysowany w jego DrawingContextobiekcie .

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

Tworzenie przesłonięć dla elementów członkowskich FrameworkElement

Obiekt kontenera hosta jest odpowiedzialny za zarządzanie kolekcją obiektów wizualnych. Wymaga to, aby kontener hosta implementować przesłonięcia składowe dla klasy pochodnej FrameworkElement .

Na poniższej liście opisano dwa elementy członkowskie, które należy zastąpić:

  • GetVisualChild: zwraca element podrzędny w określonym indeksie z kolekcji elementów podrzędnych.

  • VisualChildrenCount: pobiera liczbę elementów podrzędnych wizualizacji w ramach tego elementu.

W poniższym przykładzie są implementowane przesłonięcia dla dwóch FrameworkElement elementów członkowskich.


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

Zapewnianie obsługi testowania trafień

Obiekt kontenera hosta może zapewnić obsługę zdarzeń, nawet jeśli nie wyświetla żadnych widocznych właściwości — jednak Visibility jej właściwość musi być ustawiona na Visiblewartość . Dzięki temu można utworzyć procedurę obsługi zdarzeń dla kontenera hosta, który może wychwycić zdarzenia myszy, takie jak zwolnienie lewego przycisku myszy. Procedura obsługi zdarzeń może następnie implementować testowanie trafień przez wywołanie HitTest metody . Parametr metody HitTestResultCallback odnosi się do procedury zdefiniowanej przez użytkownika, której można użyć do określenia wynikowej akcji testu trafienia.

W poniższym przykładzie obsługa testowania trafień jest implementowana dla obiektu kontenera hosta i jego elementów podrzędnych.

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

Zobacz też