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

В этом разделе приведены общие сведения о визуальном слое WPF. В нем основное внимание уделяется роли Visual класса для поддержки отрисовки в WPF модели.

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

VisualКласс является базовой абстракцией, из которой FrameworkElement наследуется каждый объект. Эта абстракция также служит точкой входа для написания новых элементов управления WPF, и во многих случаях ее можно рассматривать в качестве дескриптора окна (HWND) в модели приложения Win32.

VisualОбъект является базовым WPF объектом, первичной ролью которого является предоставление поддержки отрисовки. Элементы управления пользовательского интерфейса, такие как Button и TextBox , являются производными от Visual класса и используют его для сохранения данных отрисовки. VisualОбъект обеспечивает поддержку следующих объектов:

  • Отображение выходных данных: визуализация сохраненного, сериализованного содержимого визуального элемента.

  • Преобразование: поддерживает преобразование визуального элемента.

  • Отсечение: позволяет указать область отсечения для визуального элемента.

  • Проверка нажатия: определяет, содержится ли координата или геометрическая фигура в границах визуального объекта.

  • Вычисление ограничивающего прямоугольника: определение ограничивающего прямоугольника визуального объекта.

Однако объект не Visual включает поддержку функций, не относящихся к отрисовке, таких как:

  • Обработка событий

  • Макет

  • Стили

  • привязка данных,

  • Глобализация

Visual предоставляется в виде открытого абстрактного класса, от которого должны наследоваться дочерние классы. На следующем рисунке показана иерархия визуальных объектов, которые предоставляются в WPF.

Схема классов, производных от Visual-объекта

Класс DrawingVisual

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

Класс Viewport3DVisual

Viewport3DVisualПредоставляет мост между 2D Visual и Visual3D объектами. Visual3DКласс является базовым классом для всех трехмерных визуальных элементов. Для Viewport3DVisual необходимо определить Camera значение и Viewport значение. Камера позволяет просмотреть сцену. Окно просмотра определяет, где проекция преобразуется в двумерную поверхность. Дополнительные сведения о трехмерном графике WPF см. в разделе Обзор трехмерной графики.

Класс ContainerVisual

ContainerVisualКласс используется в качестве контейнера для коллекции Visual объектов. DrawingVisualКласс является производным от ContainerVisual класса, что позволяет ему содержать коллекцию визуальных объектов.

Рисование содержимого в объектах Visual

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

Тип содержимого для отрисовки Описание
Векторная графика Представляет данные векторной графики, а также любые связанные данные Brush и Pen .
Образ — Представляет изображение в регионе, определенном Rect .
Глиф Представляет рисунок, который визуализирует GlyphRun , который представляет собой последовательность глифов из указанного ресурса шрифта. Таким образом представляется текст.
Видео Представляет рисунок, отображающий видео.

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

При создании WPF элемента управления, например Button , элемент управления неявно создает данные отрисовки для рисования самих себя. Например, установка Content свойства объекта Button приводит к тому, что элемент управления будет хранить представление глифа в виде отрисовки.

Объект Visual описывает его содержимое как один или несколько Drawing объектов, содержащихся в DrawingGroup . В DrawingGroup также описываются маски непрозрачности, преобразования, эффекты точечного рисунка и другие операции, применяемые к его содержимому. DrawingGroup операции применяются в следующем порядке при отображении содержимого: OpacityMask , Opacity ,,, BitmapEffect ClipGeometry GuidelineSet и Transform .

На следующем рисунке показан порядок, в котором DrawingGroup операции применяются во время последовательности отрисовки.

Порядок операций DrawingGroup
Порядок операций DrawingGroup

Дополнительные сведения см. в разделе Обзор объектов Drawing.

Отображение содержимого на визуальном уровне

Вы никогда не создаете напрямую экземпляр a DrawingContext ; однако можно получить контекст рисования из определенных методов, таких как DrawingGroup.Open и DrawingVisual.RenderOpen . В следующем примере извлекается DrawingContext из DrawingVisual и используется для рисования прямоугольника.

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

Перечисление содержимого рисования на визуальном уровне

Помимо других применений, Drawing объекты также предоставляют объектную модель для перечисления содержимого Visual .

Примечание

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

В следующем примере метод используется GetDrawing для получения DrawingGroup значения Visual и перечисления.

public void RetrieveDrawing(Visual v)
{
    DrawingGroup drawingGroup = VisualTreeHelper.GetDrawing(v);
    EnumDrawingGroup(drawingGroup);
}

// Enumerate the drawings in the DrawingGroup.
public void EnumDrawingGroup(DrawingGroup drawingGroup)
{
    DrawingCollection dc = drawingGroup.Children;

    // Enumerate the drawings in the DrawingCollection.
    foreach (Drawing drawing in dc)
    {
        // If the drawing is a DrawingGroup, call the function recursively.
        if (drawing is DrawingGroup group)
        {
            EnumDrawingGroup(group);
        }
        else if (drawing is GeometryDrawing)
        {
            // Perform action based on drawing type.
        }
        else if (drawing is ImageDrawing)
        {
            // Perform action based on drawing type.
        }
        else if (drawing is GlyphRunDrawing)
        {
            // Perform action based on drawing type.
        }
        else if (drawing is VideoDrawing)
        {
            // Perform action based on drawing type.
        }
    }
}

Использование визуальных объектов для создания элементов управления

Многие из объектов в WPF состоят из других визуальных объектов, то есть они могут содержать различные иерархии объектов-потомков. Многие элементы пользовательского интерфейса в WPF, например элементы управления, состоят из нескольких визуальных объектов, которые представляют различные типы прорисовываемых элементов. Например, Button элемент управления может содержать ряд других объектов, включая ClassicBorderDecorator , ContentPresenter и TextBlock .

В следующем коде показан Button элемент управления, определенный в разметке.

<Button Click="OnClick">OK</Button>

Если необходимо перечислить визуальные объекты, составляющие элемент управления по умолчанию Button , можно найти иерархию визуальных объектов, как показано ниже:

Схема иерархии визуального дерева

ButtonЭлемент управления содержит ClassicBorderDecorator элемент, который, в свою очередь, содержит ContentPresenter элемент. ClassicBorderDecoratorЭлемент отвечает за Рисование границы и фона для Button . ContentPresenterЭлемент отвечает за отображение содержимого объекта Button . В этом случае, поскольку отображается текст, ContentPresenter элемент содержит TextBlock элемент. Тот факт, что Button элемент управления использует, ContentPresenter означает, что содержимое может быть представлено другими элементами, например, Image или геометрией, например EllipseGeometry .

Шаблоны элементов управления

Ключом к раскрытию элемента управления в иерархии элементов управления является ControlTemplate . Шаблон элемента управления определяет визуальную иерархию по умолчанию для элемента управления. При явной ссылке на элемент управления вы неявно ссылаетесь на его визуальную иерархию. Для изменения внешнего вида элемента управления вы можете переопределить значения по умолчанию для шаблона элемента управления. Например, можно изменить значение цвета фона Button элемента управления таким образом, чтобы оно использовало значение цвета линейного градиента вместо сплошного значения цвета. Дополнительные сведения см. в разделе Стили и шаблоны кнопок.

Элемент пользовательского интерфейса, например Button элемент управления, содержит несколько списков инструкций векторной графики, описывающих все определение отрисовки элемента управления. В следующем коде показан Button элемент управления, определенный в разметке.

<Button Click="OnClick">
  <Image Source="images\greenlight.jpg"></Image>
</Button>

Если необходимо перечислить визуальные объекты и списки инструкций векторной графики, составляющие Button элемент управления, можно найти иерархию объектов, показанную ниже:

Схема визуального дерева и отрисовки данных

ButtonЭлемент управления содержит ClassicBorderDecorator элемент, который, в свою очередь, содержит ContentPresenter элемент. ClassicBorderDecoratorЭлемент отвечает за рисование всех дискретных графических элементов, составляющих границу и фон кнопки. ContentPresenterЭлемент отвечает за отображение содержимого объекта Button . В этом случае, поскольку отображается изображение, ContentPresenter элемент содержит Image элемент.

При работе с иерархией визуальных объектов и списками инструкций векторной графики следует учитывать несколько моментов.

  • Порядок иерархии представляет порядок отрисовки графической информации. От корневого визуального элемента дочерние элементы распространяются слева направо и сверху вниз. Если у элемента есть дочерние визуальные элементы, они распространяются до элементов того же уровня.

  • Неконечные элементы узла в иерархии, такие как ContentPresenter , используются для хранения дочерних элементов — они не содержат списки инструкций.

  • Если визуальный элемент содержит как список инструкций векторной графики, так и визуальные дочерние объекты, то список инструкций в родительском визуальном элементе выполняется перед тем, как будут прорисованы любые визуальные дочерние объекты.

  • Элементы в списке инструкций векторной графики обрабатываются слева направо.

Видимое дерево

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

В следующем коде показан StackPanel элемент, определенный в разметке.

<StackPanel>
  <Label>User name:</Label>
  <TextBox />
  <Button Click="OnClick">OK</Button>
</StackPanel>

Если необходимо перечислить визуальные объекты, составляющие StackPanel элемент в примере разметки, можно найти иерархию визуальных объектов, показанную ниже:

Схема иерархии визуального дерева

Порядок отрисовки

Визуальное дерево определяет порядок отрисовки визуальных элементов и графических объектов WPF. Обработка начинается с корневого визуального элемента, самого верхнего узла в визуальном дереве. Затем обрабатываются дочерние элементы корневого визуального элемента слева направо. Если у визуального элемента есть дочерние элементы, они обрабатываются перед элементами, находящимися на одном уровне с визуальным элементом. Это означает, что содержимое дочерних визуальных элементов отображается перед содержимым самого визуального элемента.

Схема порядка отрисовки визуального дерева

Корневой визуальный элемент

Корневой визуальный элемент — это самый верхний элемент в иерархии визуального дерева. В большинстве приложений базовым классом корневого визуального элемента является Window либо NavigationWindow . Однако при размещении визуальных объектов в приложении Win32 в качестве корневого визуального элемента использовался бы самый верхний визуальный элемент в окне Win32. Дополнительные сведения см. в разделе Руководство по размещению визуальных объектов в приложении Win32.

Связь с логическом деревом

Логическое дерево в WPF представляет элементы приложения во время выполнения. Хотя этим деревом нельзя управлять напрямую, с помощью этой схемы удобно представить наследование свойств и маршрутизацию событий. В отличие от визуального дерева, логическое дерево может представлять объекты данных, не являющиеся визуальными, такие как ListItem . Во многих случаях логическое дерево приближается к определению разметки приложения. В следующем коде показан DockPanel элемент, определенный в разметке.

<DockPanel>
  <ListBox>
    <ListBoxItem>Dog</ListBoxItem>
    <ListBoxItem>Cat</ListBoxItem>
    <ListBoxItem>Fish</ListBoxItem>
  </ListBox>
  <Button Click="OnClick">OK</Button>
</DockPanel>

Если необходимо перечислить логические объекты, составляющие DockPanel элемент в примере разметки, можно найти иерархию логических объектов, как показано ниже:

Схема дерева
Схема логического дерева

Визуальное дерево и логическое дерево синхронизируются с текущим набором элементов приложения, отражая добавление, удаление или изменение элементов. Однако эти деревья отражают различные представления приложения. В отличие от визуального дерева, логическое дерево не расширяет элемент элемента управления ContentPresenter . Это означает, что между логическим деревом и визуальным деревом для одного и того же набора объектов нет прямого однозначного соответствия. Фактически, вызов метода объекта LogicalTreeHelper GetChildren и метода объекта VisualTreeHelper GetChild с использованием того же элемента, что и параметр, дает разные результаты.

Дополнительные сведения о логическом дереве см. в разделе Деревья в WPF.

Просмотр визуального дерева с помощью XamlPad

WPFСредство XamlPad предоставляет возможность просмотра и исследования визуального дерева, соответствующего определенному в настоящий момент содержимому XAML. Для отображения визуального дерева нажмите кнопку Показать визуальное дерево. Ниже показано, как раскрытие содержимого XAML в узлах визуального дерева на панели обозревателя визуального дерева XamlPad:

Панель обозревателя визуального дерева в XamlPad

Обратите внимание Label , что TextBox каждый из Button элементов управления, и отображает отдельную иерархию визуальных объектов на панели обозревателя визуального дерева XamlPad. Это связано WPF с тем, что элементы управления имеют объект ControlTemplate , который содержит визуальное дерево этого элемента управления. При явной ссылке на элемент управления вы неявно ссылаетесь на его визуальную иерархию.

Профилирование производительности для объекта Visual

В состав WPF входит пакет инструментов для профилирования производительности, с помощью которых можно проанализировать поведение приложения во время выполнения и определить, каким образом можно повысить производительность. Средство Visual Profiler предоставляет подробные данные о производительности в удобном графическом формате, сопоставляя их напрямую с визуальным деревом приложения. На этом снимке экрана показан раздел Использование ЦП средства Visual Profiler. В этом разделе вы можете получить точное представление об использовании объектом служб WPF, таких как отрисовка и разметка.

Отображение данных Visual Profiler
Отображение данных Visual Profiler

Поведение отрисовки для объекта Visual

WPF включает несколько возможностей, влияющих на отрисовку визуальных объектов: графика, векторная графика и аппаратно независимая графика.

Абстрактный графический режим

Для понимания роли объекта Visual необходимо хорошо представлять различие между системами с непосредственным и абстрактным графическими режимами. В стандартном приложении Win32 на основе GDI или GDI+ используется непосредственный графический режим. Это означает, что приложение отвечает за перерисовку той части клиентской области, которая стала недействительной из-за таких действий, как изменение размера окна или изменение внешнего вида объекта.

Схема последовательности отрисовки Win32

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

Схема последовательности отрисовки WPF

Интеллектуальная перерисовка

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

Векторная графика

WPF использует векторную графику качестве формата данных отрисовки. Векторная графика, к которой относятся масштабируемые векторные рисунки (SVG), метафайлы Windows (WMF) и шрифты TrueType, хранит данные отрисовки и передает их в виде списка инструкций, которые описывают, как воссоздать изображение с помощью графических примитивов. Например, шрифты TrueType — это контурные шрифты, которые описывают набор линий, кривых и команд, а не массив точек. Одним из основных преимуществ векторной графики является возможность масштабирования до любого размера и разрешения.

В отличие от векторной графики в растровой графике данные отрисовки представлены в попиксельном виде для определенного разрешения. Одним из ключевых различий между растровой и векторной графикой является соответствие исходному изображению. Например, при изменении размера исходного изображения в растровой графике изображение растягивается, тогда как в векторной — масштабируется с сохранением качества.

На следующем рисунке показано исходное изображение, которое было увеличено в 3 раза (масштаб 300 %). Обратите внимание на искажения, которые появляются при растяжении исходного изображения в растровом формате по сравнению с векторным.

Различия между растровой и векторной графикой

В следующей разметке показаны два Path определенных элемента. Второй элемент использует ScaleTransform для изменения размера инструкций рисования первого элемента на 300%. Обратите внимание, что инструкции по рисованию в Path элементах остаются неизменными.

<Path
  Data="M10,100 C 60,0 100,200 150,100 z"
  Fill="{StaticResource linearGradientBackground}"
  Stroke="Black"
  StrokeThickness="2" />

<Path
  Data="M10,100 C 60,0 100,200 150,100 z"
  Fill="{StaticResource linearGradientBackground}"
  Stroke="Black"
  StrokeThickness="2" >
  <Path.RenderTransform>
    <ScaleTransform ScaleX="3.0" ScaleY="3.0" />
  </Path.RenderTransform>
</Path>

О разрешении и аппаратно независимой графике

Существуют два фактора, которые определяют размер текста и графики на экране: разрешение и количество точек на дюйм. Разрешение определяет число пикселей, отображаемых на экране. Чем выше разрешение, тем меньше размер пикселей и тем меньше отображаемые объекты и текст. Изображение на мониторе с разрешением 1024 x 768 значительно уменьшится, если изменить разрешение на 1600 x 1200.

Другой системный параметр, количество точек на дюйм, описывает размер дюйма экрана в пикселях. В большинстве систем Windows используется значение DPI 96, означающее, что экранный дюйм составляет 96 пикселей. При повышении количества точек на дюйм экранный дюйм увеличивается, при понижении — уменьшается. Это означает, что дюйм экрана не совпадает с размером настоящего дюйма, по крайней мере в большинстве систем. При увеличении количества точек на дюйм изображения и текст становятся больше, так как увеличивается размер экранного дюйма. Увеличение количества точек на дюйм может сделать текст более удобным для чтения, особенно при высоких разрешениях.

Не все приложения поддерживают количество точек на дюйм: в некоторых приложениях в качестве основной единицы измерения используются аппаратно зависимые пиксели, и изменение количества точек на дюйм не влияет на такие приложения. Во многих других приложениях количество точек на дюйм используется при описании размеров шрифта, но для остальных элементов используются пиксели. Слишком маленькое или слишком большое количество точек на дюйм может вызвать проблемы с разметкой для этих приложений, так как размер текста приложения будет изменяться с изменением системного количества точек на дюйм, тогда как интерфейс приложения изменяться не будет. Для приложений, разработанных с помощью WPF, эта проблема устранена.

WPF поддерживает автоматическое масштабирование с помощью аппаратно независимых пикселей вместо аппаратно зависимых пикселей; изображения и текст масштабируются правильно без дополнительных действий со стороны разработчика приложения. На следующем рисунке показан пример отображения текста и графики WPF с различными параметрами количества точек на дюйм.

Изображения и текст с различными параметрами количества точек на дюйм
Изображения и текст с различными параметрами количества точек на дюйм

Класс VisualTreeHelper

VisualTreeHelperКласс является статическим вспомогательным классом, предоставляющим низкоуровневые функции для программирования на уровне визуальных объектов, который полезен в особых сценариях, таких как разработка высокопроизводительных пользовательских элементов управления. В большинстве случаев объекты платформы более высокого уровня WPF , такие как Canvas и TextBlock , обеспечивают большую гибкость и простоту использования.

Проверка нажатия

VisualTreeHelperКласс предоставляет методы для проверки попадания на визуальные объекты, если поддержка проверки попадания по умолчанию не соответствует вашим потребностям. HitTestМетоды в классе можно использовать VisualTreeHelper для определения того, находится ли геометрический объект или координата точки внутри границы данного объекта, например элемента управления или графического элемента. Например, с помощью проверки нажатия можно определить, попадает ли щелчок мыши в пределах ограничивающего прямоугольника объекта в окружность. Также можно переопределить реализацию проверки нажатия по умолчанию и выполнять собственные вычисления для проверки нажатия.

Дополнительные сведения о проверке нажатия см. в разделе Проверка нажатия на визуальном уровне.

Перечисление визуального дерева

VisualTreeHelperКласс предоставляет функциональные возможности для перечисления элементов визуального дерева. Чтобы получить родительский объект, вызовите GetParent метод. Чтобы получить дочерний или прямой потомок визуального объекта, вызовите GetChild метод. Этот метод возвращает дочерний элемент Visual родителя по указанному индексу.

В следующем примере показано, как перечислить всех потомков визуального объекта. Этот метод можно использовать для сериализации всех данных отрисовки в иерархии визуального объекта.

// Enumerate all the descendants of the visual object.
static public void EnumVisual(Visual myVisual)
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(myVisual); i++)
    {
        // Retrieve child visual at specified index value.
        Visual childVisual = (Visual)VisualTreeHelper.GetChild(myVisual, i);

        // Do processing of the child visual object.

        // Enumerate children of the child visual object.
        EnumVisual(childVisual);
    }
}
' Enumerate all the descendants of the visual object.
Public Shared Sub EnumVisual(ByVal myVisual As Visual)
    For i As Integer = 0 To VisualTreeHelper.GetChildrenCount(myVisual) - 1
        ' Retrieve child visual at specified index value.
        Dim childVisual As Visual = CType(VisualTreeHelper.GetChild(myVisual, i), Visual)

        ' Do processing of the child visual object.

        ' Enumerate children of the child visual object.
        EnumVisual(childVisual)
    Next i
End Sub

В большинстве случаев логическое дерево более удобно для представления элементов приложения WPF. Хотя логическое дерево нельзя изменить напрямую, с помощью этой схемы удобно представить наследование свойств и маршрутизацию событий. В отличие от визуального дерева, логическое дерево может представлять объекты данных, не являющиеся визуальными, такие как ListItem . Дополнительные сведения о логическом дереве см. в разделе Деревья в WPF.

VisualTreeHelperКласс предоставляет методы для возврата ограничивающего прямоугольника визуальных объектов. Можно вернуть ограничивающий прямоугольник визуального объекта, вызвав метод GetContentBounds . Можно вернуть ограничивающий прямоугольник всех потомков визуального объекта, включая сам визуальный объект, вызвав GetDescendantBounds . В следующем коде показано, как вычислить ограничивающие прямоугольники для визуального объекта и всех его потомков.

// Return the bounding rectangle of the parent visual object and all of its descendants.
Rect rectBounds = VisualTreeHelper.GetDescendantBounds(parentVisual);
' Return the bounding rectangle of the parent visual object and all of its descendants.
Dim rectBounds As Rect = VisualTreeHelper.GetDescendantBounds(parentVisual)

См. также раздел