Compartilhar via


Visão Geral sobre Renderização de Gráficos do Windows Presentation Foundation

Este tópico fornece uma visão geral da camada visual do WPF. Concentra-se no papel da classe Visual para suporte a renderização no modelo WPF.

Este tópico contém as seguintes seções.

  • Papel do Objeto Visual
  • Como Objetos Visuais são Utilizados para Construir Controles
  • Árvore Visual
  • Comportamento de Renderização Visual
  • Classe VisualTreeHelper
  • Tópicos relacionados

Papel do Objeto Visual

A classe Visual é a abstração básica a partir da qual todo objeto FrameworkElement deriva. Também serve como ponto de entrada para escrever novos controles em WPF, e em muitas formas pode ser visto como o manipulador de janela (HWND) do modelo de aplicação Win32.

O objeto Visual é um objeto WPF central, cujo papel primário é fornecer suporte a renderização. Controles de interface de usuário, tais como Button e TextBox, derivam da classe Visual, e utilizam-na para persistir seus dados de renderização. O objeto Visual fornece suporte a:

  • Exibição de saída: Renderizar o persistentes, serializado do conteúdo do desenho de um visual.

  • Transformações: Execução de transformações em um visual.

  • Corte: Fornecendo suporte de região de recorte para um visual.

  • Teste de ocorrências: Determinando se uma coordenada ou geometria está contida dentro dos limites de um visual.

  • Cálculos de caixa delimitadora: Determinando o retângulo delimitador de um visual.

Entretanto, o objeto Visual não inclui suporte a características de não renderização, tais como:

  • Tratamento de eventos

  • Layout

  • Estilos

  • Ligação de Dados

  • Globalização

Visual é exposta como uma classe abstrata pública a partir da qual classes filhas devem ser derivadas. A ilustração a seguir mostra a hierarquia dos objetos visuais que são expostos em WPF.

Hierarquia de classes visuais

Diagrama de classes derivadas do objeto Visual

Classe DrawingVisual

A DrawingVisual é uma classe leve utilizada para renderizar formas, imagens ou texto. Essa classe é considerada leve porque não fornece layout ou tratamento de eventos, o que aumenta seu desempenho em tempo de execução. Por este motivo, os desenhos são ideais para planos de fundo e clip art. The DrawingVisual pode ser usado para criar um objeto visual personalizado. Para obter mais informações, consulte Using DrawingVisual Objects.

Classe Viewport3DVisual

O Viewport3DVisual fornece uma ponte entre objetos 2D Visual e Visual3D. A classe Visual3D é a classe base para todos os elementos visuais 3D. A Viewport3DVisual requer que você defina um valor Camera e um valor Viewport. A câmera que você visualize a cena. O viewport estabelece onde a projeção mapeia na superfície 2D. Para obter mais informações sobre 3D emWPF, consulte Visão geral de elementos gráficos 3D.

Classe ContainerVisual

A classe ContainerVisual é utilizada como um contêiner para uma coleção de objetos Visual. A classe DrawingVisual deriva de uma classe ContainerVisual, permitindo que ela contenha uma coleção de objetos visuais.

Desenhando Conteúdo em Objetos Visuais

Um objeto Visual armazena seus dados de renderização como uma lista de instruções de gráfico vetorial. Cada item na lista de instruções representa um conjunto de baixo nível de dados gráficos e recursos associados num formato serializável. Há quatro tipos diferentes de dados de renderização que podem conter conteúdo de desenho.

Tipo de conteúdo de desenho

Descrição

Gráfico vetorial

Representa dados de gráfico vetorial e quaisquer informações Brush e Pen associadas.

Image

Representa uma imagem dentro de uma região definida por um Rect.

Glifo

Representa um desenho que renderiza um GlyphRun que é uma sequência de glifos de um recurso de fonte especificado. É assim que texto é representado.

Vídeo

Representa um desenho que renderiza vídeo.

O DrawingContext permite que você popule um Visual com conteúdo visual. Quando você utiliza os comandos de desenho de um objeto DrawingContext, você está de fato armazenando um conjunto de dados de renderização que serão utilizados mais tarde pelo sistema gráfico; você não está desenhando na tela em tempo real.

Quando você cria um controle WPF, tal como Button, o controle implicitamente gera dados de renderização para o próprio desenho. Por exemplo, definir a propriedade Content do Button faz com que o controle armazene uma representação renderizada de um glifo.

Um Visual descreve seu conteúdo como um ou mais objetos Drawing contidos em um DrawingGroup. A DrawingGroup também descreve máscaras de opacidade, transformações, efeitos de bitmap e outras operações que são aplicadas ao seu Sumário. DrawingGroup as operações são aplicadas na seguinte ordem quando conteúdo for processado: OpacityMask, Opacity, BitmapEffect, ClipGeometry, GuidelineSete, em seguida, Transform.

A ilustração a seguir mostra a ordem em que operações DrawingGroup são aplicadas durante a sequência de renderização.

Ordem de operações DrawingGroup

Ordem de operações de DrawingGroup

Para obter mais informações, consulte Visão Geral de Objetos de Desenho.

Desenhando Conteúdo na Camada Visual

Você nunca instancia diretamente um DrawingContext; você pode, no entanto, adquirir um contexto de desenho de alguns métodos, tais como DrawingGroup.Open e DrawingVisual.RenderOpen. O exemplo a seguir recupera um DrawingContext de um DrawingVisual e utiliza-o para desenhar um retângulo.

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

Enumerando Conteúdo de Desenho na Camada Visual

Além de seus outros usos, objetos Drawing também fornecem um modelo de objeto para enumerar os conteúdos de um Visual.

ObservaçãoObservação:

Quando são enumerar o Sumário do visual, você está recuperando Drawing objetos e não a subjacente representação dos dados de processamento sistema autônomo uma lista de instrução de elementos gráficos vetoriais.

O exemplo a seguir utiliza o método GetDrawing para recuperar o valor DrawingGroup de um Visual e enumerá-lo.

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

}

 // 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.GetType() == typeof(DrawingGroup))
         {
             EnumDrawingGroup((DrawingGroup)drawing);
         }
         else if (drawing.GetType() == typeof(GeometryDrawing))
         {
             // Perform action based on drawing type.  
         }
         else if (drawing.GetType() == typeof(ImageDrawing))
         {
             // Perform action based on drawing type.
         }
         else if (drawing.GetType() == typeof(GlyphRunDrawing))
         {
             // Perform action based on drawing type.
         }
         else if (drawing.GetType() == typeof(VideoDrawing))
         {
             // Perform action based on drawing type.
         }
     }
 }

Como Objetos Visuais são Utilizados para Construir Controles

Muitos dos objetos em WPF são compostos de outros objetos visuais, o que significa que podem conter diversas hierarquias de objetos descendentes. Muitos dos elementos de interface de usuário em WPF, tais como controles, são compostos de múltiplos objetos visuais, representando diferentes tipos de elementos de renderização. Por exemplo, o controle Button pode conter diversos outros objetos, incluindo ClassicBorderDecorator, ContentPresenter e TextBlock.

O código a seguir mostra um controle Button definido em marcação.

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

Se você fosse enumerar os objetos visuais que compreendem o controle Button default, você descobriria a hierarquia de objetos visuais ilustrada abaixo:

Diagrama de hierarquia de árvore visual

Diagrama de hierarquia de árvore visual

O controle Button contém um elemento ClassicBorderDecorator, que por sua vez contém um elemento ContentPresenter. O elemento ClassicBorderDecorator é responsavel por desenhar uma borda e um fundo para o Button. O elemento ContentPresenter é responsável por exibir os conteúdos do Button. Nesse caso, como você está exibindo texto, o elemento ContentPresenter contém um elemento TextBlock. O fato que o controle Button utiliza um ContentPresenter significa que o conteúdo poderia ser representado por outros elementos, tal como Image ou uma geometria, tal como um EllipseGeometry.

Modelos de Controle

A chave para expansão de um controle em uma hierarquia de controles é o ControlTemplate. Um modelo de controle especifica a hierarquia visual defaul de um controle. Quando você referencia um controle explicitamente, você implicitamente referencia sua hierarquia visual. Você pode sobrepor os valores defaults de um modelo de controle para cirar uma aparência visual personalizada para um controle. Por exemplo, você poderia modificar o valor de cor de fundo do controle Button para que utilize um valor de cor gradiente linear em vez de um valor de cor sólido. Para obter mais informações, consulte Exemplo de Modelo de Controle de Botão.

Um elemento de interface de usuário, tal como o controle Button, contém diversas listas de instrução de gráfico vetorial que descrevem a definição de renderização completa do controle. O código a seguir mostra um controle Button definido em marcação.

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

Se você fosse enumerar os objetos visuais e as listas de instrução de gráfico vetorial que compreendem o controle Button default, você descobriria a hierarquia de objetos visuais ilustrada abaixo:

Diagrama de árvore visual e dados de renderização

Diagrama de árvore visual e dados de renderização

O controle Button contém um elemento ClassicBorderDecorator, que por sua vez contém um elemento ContentPresenter. O elemento ClassicBorderDecorator é responsável por desenhar todos os elementos gráficos discretos que compõem a borda e o fundo de um botão. O elemento ContentPresenter é responsável por exibir os conteúdos do Button. Nesse caso, como você está exibindo uma imagem, o elemento ContentPresenter contém um elemento Image.

Há diversos pontos a observar sobre a hierarquia de objetos visuais e listas de instrução de gráfico vetorial:

  • A ordem na hierarquia representa a ordem de renderização da informação de desenho. A partir do elemento visual raiz, elementos filhos são percorridos, da esquerda para a direita e de cima para baixo. Se um elemento possui elementos filhos visuais, eles são percorridos antes dos irmãos do elemento.

  • Elementos de nós não folha na hierarquia, tais como ContentPresenter, são utilizados para conter elementos filhos -- eles não contêm listas de instrução.

  • Se um elemento visual contém tanto uma lista de instrução de gráfico vetorial quanto filhos visuais, a lista de instruções no elemento visual pai é renderizada antes dos desenhos de quaisquer objetos visuais filhos.

  • Os itens na lista de instruções de gráfico vetorical são renderizadas da esquerda para a direita.

Árvore Visual

A árvore visual contém todos os elementos visuais usados na interface do usuário do aplicativo. Como um elemento visual contém informações de desenho persistidas, você pode ver a árvore visual como um grafo de cena, contendo todas as informações de renderização necessárias para compor a saída para o dispositivo de exibição. Esta árvore é o acúmulo de todos os elementos visuais criados diretamente pela aplicação, seja por código ou marcação. A árvore visual também contém todos os elementos visuais criados pela expansão de modelo de elementos tais como controles e objetos de dados.

O código a seguir mostra um controle StackPanel definido em marcação.

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

Se você fosse enumerar os objetos visuais que compreendem o elemento StackPanel no exemplo de marcação, você descobriria a hierarquia de objetos visuais ilustrada abaixo:

Diagrama de hierarquia de árvore visual

Diagrama de hierarquia de árvore visual

Ordem de Renderização

A árvore visual determina a ordem de renderização dos objetos visuais e de desenho WPF. A ordem de percurso inicia com o visual raiz, que é o nó mais no topo na árvore visual. Os filhos do visual raiz são então percorridos, da esquerda para a direita. Se um visual possuir filhos, seus filhos são percorridos antes de seus irmãos. Isso significa que o conteúdo de um visual filho é renderizado antes do conteúdo do próprio visual.

Diagrama de ordem de renderização de árvore visual

Diagrama de ordem de renderização de árvore visual

Visual Raiz

O visual raiz é o elemento mais no topo de uma hierarquia visual. Na maioria das aplicações, a classe base do visual raiz é Window ou NavigationWindow. Entretanto, se você estivesse hospedando objetos visuais numa aplicação Win32, o visual raiz seria o visual mais no topo que você estivesse hospedando na janela Win32. Para obter mais informações, consulte Tutorial: Hospedagem Visual objetos em um aplicativo Win32.

Relacionamento com a Árvore Lógica

A árvore lógica em WPF representa os elementos de um aplicativo em time de execução. Embora você não manipule esta árvore diretamente, essa visão da aplicação é útil para entender a herança de propriedades e o roteamento de eventos. Diferente da árvore visual, a árvore lógica pode representar objetos de dados não visuais, tal como ListItem. Em muitos casos, a árvore lógica mapeia muito próximo às definições de marcação de uma aplicação. O código a seguir mostra um controle DockPanel definido em marcação.

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

Se você fosse enumerar os objetos lógicos que compreendem o elemento DockPanel no exemplo de marcação, você descobriria a hierarquia de objetos lógicos ilustrada abaixo:

Diagrama de árvore lógica

Diagrama de árvore

Ambas árvores visual e lógica são sincronizadas com o conjunto atual de elementos da aplicação, refletindo qualquer adição, remoçao ou modificação de elementos. Entretanto, as árvores apresentam diferentes visões da aplicação. Diferente da árvore visual, a árvore lógica não expande o elemento ContentPresenter de um controle. Isso significa que não há uma correspondência direta um para um entre uma árvore lógica e uma árvore visual para o mesmo conjunto de objetos. De fato, invocar o metodo GetChildren do objeto LogicalTreeHelper e o metodo GetChild do objeto VisualTreeHelper utilizando o mesmo elemento como parâmetro dá resultados diferentes.

Para mais informações sobre a árvore lógica, veja Árvores em WPF.

Visualizando a Árvore Visual com XamlPad

A ferramenta WPF, XamlPad, fornece uma opção para visualizar e explorar a árvore visual que corresponde ao conteúdo XAML atualmente definido. Clique no botão Show Visual Tree na barra de menus para exibir a árvore visual. A seguir ilustra-se a expansão do conteúdo XAML em nós de árvore visual no painel Visual Tree Explorer do XamlPad:

Painel do gerenciador de árvore visual no XamlPad

Painel do gerenciador de árvore visual no XamlPad

Observe como os controles Label, TextBox e Button exibem cada um uma hierarquia de objetos visuais separada no painel Visual Tree Explorer do XamlPad. Isso ocorre porque controles WPF têm um ControlTemplate que contém a árvore visual daquele controle. Quando você referencia um controle explicitamente, você implicitamente referencia sua hierarquia visual.

Traçando Perfil de Desempenho Visual

WPF fornece um conjunto de ferramentas para traçar o perfil de desempenho que lhe permitem analisar o comportamento em tempo de execução da sua aplicação e determinar que tipos de otimização de desempenho você pode aplicar. A ferramenta Visual Profiler fornece uma visão gráfica rica de dados de desempenho mapeando diretamente na árvore visual da aplicação. Nessa tela, a seção CPU Usage do Visual Profiler lhe dá um detalhamento preciso do uso de um objeto de serviços WPF, tais como renderização e layout.

Saída da exibição do Visual Profiler

Saída da exibição do Visual Profiler

Para obter mais informações sobre ferramentas de desempenho do WPF, consulte Desempenho perfil ferramentas para WPF.

Comportamento de Renderização Visual

WPF apresenta vários recursos que afetam o comportamento de renderização de objetos visuais: retidos de modo de gráficos, gráficos vetoriais e gráficos independentes de dispositivo.

Gráfico em Modo Retido

Uma das chaves para entender o papel do objeto Visual é entender a diferença entre sistemas gráficos de modo imediato e modo retido. Uma aplicação Win32 padrão baseada em GDI ou GDI+ utiliza um sistema gráfico de modo imediato. Isso significa que a aplicação é responsável por repintar a porção da área cliente que for invalidada, devido a uma ação como um redimensionamento de janela ou um objeto mudar sua aparência visual.

Diagrama de sequência de renderização Win32

Diagrama de sequência de renderização Win32

Em contrapartida, WPF utilize um sistema em modo retido. Isso significa que os objetos de aplicação que possuem aparência visual definem um conjunto de dados de desenho serializados. Uma vez que os dados de desenho tenham sido definidos, o sistema é responsável a partir de então por responder a todas as solicitações de repintura para renderizar objetos da aplicação. Mesmo em tempo de execução, você pode modificar ou criar objetos de aplicação, e ainda assim se fiar no sistema para responder às solicitações e pintura. O poder de um sistema gráfico em modo retido é que a informação de desenho sempre é persistida num estado serializado pela aplicação, mas a responsabilidade da renderização é deixada para o sistema. O diagrama a seguir mostra como a aplicação se fia no WPF para responder às solicitaçoes de pintura.

Diagrama de sequência de renderização WPF

Diagrama de sequência de renderização WPF

Redesenho Inteligente

Um dos maiores benefícios de utilizar gráficos em modo retido é que WPF pode otimizar de forma eficiente o que precisa ser redesenhado na aplicação. Mesmo que você tenha uma cena complexa com diversos níveis de opacidade, você geralmente não precisa escrever código de propósito especial para otimizar o redesenho. Compare isso com programação em Win32 na qual você pode gastar um monte de esforço otimizando sua aplicação minimizando a quantidade de redesenho na região de atualização. See Redesenhar da região de atualização para obter um exemplo do tipo de complexidade envolvida na otimização de redesenho em aplicativos Win32.

Gráfico vetorial

WPF utiliza gráfico vetorial como seu formato de dados de renderização. Gráficos vetoriais -- que incluem Scalable Vector Graphics (SVG), Windows metafiles (.wmf) e fontes TrueType —armazenam dados de renderização e os transmitem como uma lista de instruções que descrevem como recriar uma imagem utilizando primitivas g?aficas. Por exemplo, fontes TrueType são fontes de contorno que descrevem um conjunto de linhas, curvas e comandos, em vez de um vetor de pixels. Um dos benefícios-chave de gráfico vetorial é a habilidade de redimensionar para qualquer tamanho e resolução.

Diferente de gráficos vetoriais, gráficos de bitmap armazenam dados de renderização como uma representação pixel por pixel de uma imagem, pré-renderizada por uma resolução específica. Uma das principais diferenças entre formatos de gráfico de bitmap e vetorial é a fidelidade à imagem original. Por exemplo, quando o tamanho de uma imagem de origem é modificado, sistemas de gráficos de bitmap esticam a imagem, ao passo que sistemas de gráfico vetorial redimensionam a imagem, preservando a fidelidade da imagem.

A ilustração a seguir mostra uma imagem fonte que foi redimensionada por 300%. Observe que as distorções que aparecem quando a imagem de origem é redimensionada como uma imagem de gráfico de bitmap em vez de uma imagem de gráfico vetorial.

Diferenças entre elementos gráficos de varredura e vetoriais

Diferenças entre elementos gráficos de varredura e vetoriais

A marcação a seguir mostra dois elementos Path definidos. O segundo elemento utiliza um ScaleTransform para redimensionar as instruções de desenho do primeiro elemento em 300%. Observe que as instruções de desenho nos elemento Path permanecem inalteradas.

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

Sobre Resolução e Gráficos Independentes de Dispositivo

Há dois fatores de sistema que determinam o dimensionar do texto e elementos gráficos na tela: resolução e DPI. Resolução descreve o número de pixels que aparecem na tela. Na medida em que a resolução aumenta, os pixels diminuem, fazendo com que o gráfico e texto apareçam menores. Um gráfico exibido em um monitor configurado como 1024 x 768 aparecerá bem menor quando a resolução é alterada para 1600 x 1200.

A outra configuração de sistema, DPI, descreve o tamanho da polegada de tela em pixels. A maioria dos sistemas Windows têm DPI 96, o que significa que uma polegada na tela tem 96 pixels. Aumentar a configuração de DPI torna a polegada de tela maior; diminuir o DPI torna a polegada de tela menor. Isso significa que uma polegada de tela não é do mesmo tamanho que uma polegada no mundo real; na maioria dos sistemas, provavelmente não é. Na medida em que você aumenta o DPI, gráficos e texto conscientes de DPI se tornam maiores porque você aumentou o tamanho da polegada de tela. Aumentar o DPI pode tornar o texto mais fácil de ler, especialmente em resoluções altas.

Nem todos os aplicativos são com reconhecimento de DPI: alguns usam hardware pixels sistema autônomo a principal unidade de medida; alterar o sistema de dpi não possui efeito nesses aplicativos. Muitas outras aplicações utilizam unidades conscientes de DPI para descobrir tamanhos de fonte, mas utilizam pixels para descrever tudo o mais. Tornar o DPI pequeno ou grande demais pode causar problemas de layout para essas aplicaçoes, porque o texto da aplicação é redimensionado com a configuração de DPI do sistema, mas a IU da aplicação não. Esse problema foi eliminado para aplicações desenvolvidas utilizando WPF.

WPF suporte automático dimensionamento usando o pixel independentes de dispositivo sistema autônomo sua principal unidade de medida, em vez de pixels de hardware; gráficos e texto dimensionar corretamente sem nenhum trabalho extra de desenvolvedor do aplicativo. A ilustração a seguir mostra um exemplo de como texto e gráficos de WPF aparecem em diferentes configurações de DPI.

Gráficos e texto em diferentes configurações de DPI

Gráficos e texto em diferentes configurações de DPI

Classe VisualTreeHelper

A classe VisualTreeHelper é uma classe auxiliar estática que fornece funcionalidade de baixo nível para programação no nível de objeto visual, o que é útil em cenários muito específicos, tal como o desenvolvimento de controles personalizados de alto desempenho. Na maioria dos caoss, os objetos de framework de alto nível WPF, tais como Canvas e TextBlock, oferecem maior flexibilidade e facilidade de uso.

Teste de Hit

A classe VisualTreeHelper fornece métodos para teste de hit em objetos visuais quando o suporte de teste de hit default não satisfaz sua necessidade. Você pode utilizar os métodos HitTest na classe VisualTreeHelper para determinar se um valor de geometria ou coordenada de ponto está dentro das fronteiras de um dado objeto, tal como um controle ou elemento gráfico. Por exemplo, você pode utilizar o teste de hit para determinar se um clique do mouse dentro do retângulo de fronteira de um objeto está dentro da geometria de um círculo. Você também pode escolher sobrepor a implementação default de teste de hit para desempenhar seus próprios cálculos de teste de hit.

Para obter mais informações sobre teste de hit, consulte Hit Testing in the Visual Layer.

Enumerando a Árvore Visual

A classe VisualTreeHelper fornece funcionalidade para enumerar os membros de uma árvore visual. Para recuperar um pai, chame o método GetParent. Para recuperar um filho, ou descendente direto, de um objeto visual, chame o método GetChild. Esse método retorna um filho Visual do pai no índice especificado.

O exemplo a seguir mostra como enumerar todos os descendentes de um objeto visual, que é uma técnica que você pode querer usar se você estiver interessado em serializar a informação de renderização da hierarquia de um objeto 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);
    }
}

Na maioria dos casos, a árvore lógica é uma representação mais útil dos elementos em uma aplicação WPF. Embora você não manipule a árvore lógica diretamente, essa visão da aplicação é útil para entender a herança de propriedades e o roteamento de eventos. Diferente da árvore visual, a árvore lógica pode representar objetos de dados não visuais, tal como ListItem. Para mais informações sobre a árvore lógica, veja Árvores em WPF.

A classe VisualTreeHelper fornece métodos para retornar o retângulo de fronteiras de objetos visuais. Você pode retornar o retângulo de fronteiras de um objeto visual chamando GetContentBounds. Você pode retornar o retângulo de fronteiras de todos os descendentes de um objeto visual, incluindo o próprio objeto visual, chamando GetDescendantBounds. O código a seguir mostra como você calcularia o retângulo de fronteiras de um objeto visual e todos os seus descendentes.

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

Consulte também

Conceitos

Otimizando o desempenho: 2D Graphics and Imaging

Hit Testing in the Visual Layer

Using DrawingVisual Objects

Tutorial: Hospedagem Visual objetos em um aplicativo Win32

Optimizing WPF Application Performance

Referência

Visual

VisualTreeHelper

DrawingVisual