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


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

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

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

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

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

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

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

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

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

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

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

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

  • Макет

  • Стили

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

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

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

Diagram of classes derived from the Visual object

Класс DrawingVisual

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

Класс Viewport3DVisual

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

Класс ContainerVisual

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

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

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

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

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

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

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

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

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

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

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

Создать экземпляр 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 по умолчанию, обратитесь к иерархии визуальных объектов, показанной на рисунке ниже:

Diagram of visual tree hierarchy

Элемент управления 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, обратитесь к иерархии объектов, показанной на рисунке ниже:

Diagram of visual tree and rendering data

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

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

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

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

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

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

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

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

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

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

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

Diagram of visual tree hierarchy of a StackPanel control.

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

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

Diagram of the visual tree rendering order

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

Корневой визуальный элемент — это самый верхний элемент в иерархии визуального дерева. В большинстве приложений базовый класс визуального объекта корня представляет собой 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, обратитесь к иерархии логических объектов, показанной на рисунке ниже:

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

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

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

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

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

Visual Tree Explorer panel in XamlPad

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

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

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

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

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

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

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

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

Diagram of Win32 rendering sequence

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

Diagram of WPF rendering sequence

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

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

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

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

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

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

Differences between raster and vector graphics

В следующей разметке показаны два определенных элемента 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 количество точек на дюйм составляет 96, т. е. на одном дюйме экрана находится 96 пикселей. При повышении количества точек на дюйм экранный дюйм увеличивается, при понижении — уменьшается. Это означает, что дюйм экрана не совпадает с размером настоящего дюйма, по крайней мере в большинстве систем. При увеличении количества точек на дюйм изображения и текст становятся больше, так как увеличивается размер экранного дюйма. Увеличение количества точек на дюйм может сделать текст более удобным для чтения, особенно при высоких разрешениях.

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

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

Graphics and text at different DPI settings
Изображения и текст с различными параметрами количества точек на дюйм

Класс 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)

См. также