Поделиться через


Использование объектов DrawingVisual

Этот раздел содержит обзор использования объектов DrawingVisual в визуальном слое WPF.

В этом разделе содержатся следующие подразделы.

  • Рисование визуального объекта

  • Контейнер DrawingVisual

  • Создание объектов DrawingVisual

  • Создание переопределений членов FrameworkElement

  • Предоставление поддержки проверки попадания

  • Связанные разделы

Объект DrawingVisual

Объект DrawingVisual представляет собой облегченный класс рисования, который используется для отображения фигур, рисунков или текста. Этот класс считается упрощенным, поскольку он не предоставляет макет или обработку событий, что повышает его производительность. По этой причине эти объекты идеально подходят для фоновых рисунков и коллекций картинок.

Контейнер узла DrawingVisual

Чтобы использовать объекты DrawingVisual, необходимо создать контейнер узла для объектов. Объект контейнера узла должен быть производным от класса FrameworkElement, который предоставляет макет и обеспечивает обработку событий, не поддерживаемых классом DrawingVisual. Объект контейнера узла не отображает все свойства видимости, поскольку его основной целью является содержание дочерних объектов. Однако для свойства Visibility контейнера узла должно быть установлено значение Visible; в противном случае, ни один из его дочерних элементов не будет отображен.

При создании объекта контейнера узла для визуальных объектов необходимо сохранить ссылки визуального объекта в коллекции VisualCollection. Используйте метод Add, чтобы добавить визуальный объект в контейнер узла. В следующем примере создается объект контейнер узла и три визуальных объекта, которые добавляются к его коллекции 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);
    }
ПримечаниеПримечание

Полный пример кода, из которого был взят предыдущий пример, см. на веб-странице Hit Test Using DrawingVisuals Sample.

Создание объектов DrawingVisual

При создании в объекте DrawingVisual отсутствует содержимое рисунка. Можно добавить текст, рисунок или изображение, извлекая содержимое DrawingContext объекта и рисуя в него. Объект DrawingContext возвращается путем вызова метода RenderOpen объекта DrawingVisual.

Чтобы нарисовать прямоугольник в содержимое DrawingContext, используйте метод DrawRectangle объекта DrawingContext. Похожие методы существуют для рисования других типов содержимого. Закончив рисование в содержимое DrawingContext, вызовите метод Close, чтобы закрыть объект DrawingContext и сохранить содержимое.

В следующем примере создается объект DrawingVisual, и прямоугольник рисуется в его содержимое 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;
}

Создание переопределений членов FrameworkElement

Объект контейнера узла отвечает за управление его коллекцией визуальных объектов. Для этого необходимо, чтобы контейнер узла реализовывал переопределения членов производного класса FrameworkElement.

Далее перечислены два члена, которые необходимо переопределить:

  • Член GetVisualChild: возвращает дочерний элемент по указанному индексу из коллекции дочерних элементов.

  • Член VisualChildrenCount: получает число визуальных дочерних элементов внутри этого элемента.

В следующем примере реализуются переопределение для двух членов 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];
        }

Предоставление поддержки проверки попадания

Объект контейнера узла может обеспечивать обработку события, даже если оно не отображает никаких свойств видимости, однако для его свойства Visibility должно быть установлено значение Visible. Это позволяет создать процедуру обработки события для контейнера узла, которая может перехватить события мыши, например отпускание левой кнопки. Процедура обработки события может затем реализовать проверку попадания путем вызова метода HitTest. Параметр HitTestResultCallback этого метода относится к процедуре, определенной пользователем, которую можно использовать для определения итогового действия проверки попадания.

В следующем примере проверка попадания реализуется для объекта контейнера узла и его дочерних элементов.

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

См. также

Ссылки

DrawingVisual

HitTest

Основные понятия

Общие сведения об отрисовке графики в WPF

Проверка попадания на визуальном уровне