Compartir a través de


Información general sobre la representación de gráficos de WPF

En este tema se proporciona información general sobre la capa visual de WPF. Se centra en el papel de la Visual clase para el soporte de representación en el modelo WPF.

Rol del objeto visual

La Visual clase es la abstracción básica de la que deriva cada FrameworkElement objeto. También sirve como punto de entrada para escribir nuevos controles en WPF y, de muchas maneras, se puede considerar como el identificador de ventana (HWND) en el modelo de aplicación Win32.

El Visual es un elemento principal de WPF, cuyo rol principal es proporcionar soporte para la representación. Los controles de interfaz de usuario, como Button y TextBox, derivan de la Visual clase y los usan para conservar sus datos de representación. El Visual objeto proporciona compatibilidad con:

  • Visualización de salida: representación del contenido de dibujo persistente y serializado de un elemento visual.

  • Transformaciones: realizar transformaciones en un objeto visual.

  • Recorte: proporcionar soporte para la región de recorte para un objeto visual.

  • Pruebas de detección de impacto: determinar si una coordenada o geometría está contenida dentro de los límites de un elemento visual.

  • Cálculos de rectángulo de límite: determinar el rectángulo delimitador de un objeto visual.

Sin embargo, el Visual objeto no incluye compatibilidad con características que no son de representación, como:

  • Control de eventos

  • Diseño

  • Estilos

  • Vinculación de datos

  • Globalización

Visual se expone como una clase abstracta pública de la que se deben derivar las subclases. En la ilustración siguiente se muestra la jerarquía de los objetos visuales que se exponen en WPF.

Diagrama de clases derivadas del objeto Visual

Clase DrawingVisual

DrawingVisual es una clase de dibujo ligera que se usa para representar formas, imágenes o texto. Esta clase se considera ligera porque no proporciona diseño ni control de eventos, lo que mejora su rendimiento en tiempo de ejecución. Por esta razón, los dibujos son ideales para fondos y imágenes prediseñadas. DrawingVisual se puede usar para crear un objeto visual personalizado. Para obtener más información, vea Uso de objetos DrawingVisual.

Clase Viewport3DVisual

Viewport3DVisual proporciona un puente entre 2D Visual y Visual3D objetos. La Visual3D clase es la clase base para todos los elementos visuales 3D. Viewport3DVisual requiere que defina un Camera valor y un Viewport valor. La cámara permite ver la escena. La área de visualización establece dónde se mapea la proyección en la superficie 2D. Para obtener más información sobre 3D en WPF, vea Información general sobre gráficos 3D.

ContainerVisual (clase)

La ContainerVisual clase se usa como contenedor para una colección de Visual objetos . La DrawingVisual clase deriva de la ContainerVisual clase , lo que le permite contener una colección de objetos visuales.

Dibujo de contenido en objetos visuales

Un Visual objeto almacena sus datos de representación como una lista de instrucciones de gráficos vectoriales. Cada elemento de la lista de instrucciones representa un conjunto de datos gráficos de bajo nivel y recursos asociados en un formato serializado. Hay cuatro tipos diferentes de datos de representación que pueden contener contenido de dibujo.

Tipo de contenido de dibujo Descripción
Gráficos vectoriales Representa los datos de gráficos vectorialesBrush y cualquier información asociadaPen.
Imagen Representa una imagen dentro de una región definida por .Rect
Glifo Representa un dibujo que muestra un GlyphRun, que es una secuencia de glifos de un recurso de fuente especificado. Así es como se representa el texto.
Vídeo Representa un dibujo que procesa y muestra vídeo.

DrawingContext permite rellenar un Visual objeto con contenido visual. Cuando utilizas los comandos de dibujo de un objeto DrawingContext, realmente estás almacenando un conjunto de datos de representación que posteriormente usará el sistema gráfico; no estás dibujando en la pantalla en tiempo real.

Al crear un control WPF, como Button, el control genera implícitamente datos de representación para dibujarse a sí mismo. Por ejemplo, establecer la Content propiedad de Button hace que el control almacene una representación visual de un glifo.

Un Visual describe su contenido como uno o varios Drawing objetos contenidos dentro de un DrawingGroup. También DrawingGroup describe máscaras de opacidad, transformaciones, efectos de mapa de bits y otras operaciones que se aplican a su contenido. DrawingGroupLas operaciones se aplican en el orden siguiente cuando se representa el contenido: OpacityMask, Opacity, BitmapEffect, ClipGeometry, GuidelineSet y, a continuación, Transform.

En la ilustración siguiente se muestra el orden en el que DrawingGroup se aplican las operaciones durante la secuencia de representación.

Grupo de dibujo: orden de operaciones
Orden de operaciones del grupo de dibujo

Para obtener más información, vea Información general sobre objetos de dibujo.

Dibujo de contenido en la capa visual

Nunca creas directamente una instancia de DrawingContext; sin embargo, puedes adquirir un contexto de dibujo a partir de ciertos métodos, como DrawingGroup.Open y DrawingVisual.RenderOpen. En el ejemplo siguiente, se obtiene un DrawingContext de un DrawingVisual y se usa para dibujar un rectá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;
}
' 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

Listar el contenido gráfico en la capa visual

Además de sus otros usos, Drawing los objetos también proporcionan un modelo de objetos para enumerar el contenido de .Visual

Nota:

Al enumerar el contenido del objeto visual, está recuperando Drawing objetos y no la representación subyacente de los datos de representación como una lista de instrucciones de gráficos vectoriales.

En el siguiente ejemplo se usa el método GetDrawing para recuperar el valor DrawingGroup de un Visual y enumerarlo.

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

Cómo se usan los objetos visuales para compilar controles

Muchos de los objetos de WPF se componen de otros objetos visuales, lo que significa que pueden contener jerarquías variables de objetos descendientes. Muchos de los elementos de la interfaz de usuario de WPF, como los controles, se componen de varios objetos visuales, que representan diferentes tipos de elementos de representación. Por ejemplo, el Button control puede contener una serie de otros objetos, incluidos ClassicBorderDecorator, ContentPresentery TextBlock.

El siguiente código muestra un Button control definido en el etiquetado.

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

Si tuviera que enumerar los objetos visuales que componen el control predeterminado Button , encontraría la jerarquía de objetos visuales que se muestra a continuación:

Diagrama de la jerarquía de árboles visuales

El Button control contiene un ClassicBorderDecorator elemento, que, a su vez, contiene un ContentPresenter elemento . El ClassicBorderDecorator elemento es responsable de dibujar un borde y un fondo para .Button El ContentPresenter elemento es responsable de mostrar el contenido de .Button En este caso, dado que se muestra texto, el ContentPresenter elemento contiene un TextBlock elemento . El hecho de que el Button control use un ContentPresenter significa que el contenido podría representarse mediante otros elementos, como un Image o una geometría, como un EllipseGeometry.

Plantillas de control

La clave para la expansión de un control en una jerarquía de controles es el ControlTemplate. Una plantilla de control especifica la jerarquía visual predeterminada de un control. Al hacer referencia explícitamente a un control, se hace referencia implícitamente a su jerarquía visual. Puede invalidar los valores predeterminados de una plantilla de control para crear una apariencia visual personalizada para un control. Por ejemplo, puede modificar el valor de color de fondo del Button control para que use un valor de color degradado lineal en lugar de un valor de color sólido. Para obtener más información, vea Estilos y plantillas de botón.

Un elemento de interfaz de usuario, como un Button control, contiene varias listas de instrucciones de gráficos vectoriales que describen toda la definición de representación de un control. El siguiente código muestra un Button control definido en el etiquetado.

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

Si tuviera que enumerar los objetos visuales y las listas de instrucciones de gráficos vectoriales que componen el Button control, encontraría la jerarquía de objetos ilustrados a continuación:

Diagrama del árbol visual y de los datos de representación

El Button control contiene un ClassicBorderDecorator elemento, que, a su vez, contiene un ContentPresenter elemento . El ClassicBorderDecorator elemento es responsable de dibujar todos los elementos gráficos discretos que componen el borde y el fondo de un botón. El ContentPresenter elemento es responsable de mostrar el contenido de .Button En este caso, dado que se muestra una imagen, el ContentPresenter elemento contiene un Image elemento .

Hay varios puntos que se deben tener en cuenta sobre la jerarquía de objetos visuales y listas de instrucciones de gráficos vectoriales:

  • El orden de la jerarquía representa el orden de representación de la información de dibujo. Desde el elemento visual raíz, los elementos secundarios se recorren de izquierda a derecha y de arriba a abajo. Si un elemento tiene elementos secundarios visuales, se recorren antes de los hermanos del elemento.

  • Los elementos nodales no hoja de la jerarquía, como ContentPresenter, actúan como contenedores de elementos secundarios; no contienen listas de instrucciones.

  • Si un elemento visual contiene una lista de instrucciones de gráficos vectoriales y elementos secundarios visuales, la lista de instrucciones del elemento visual primario se representa antes de dibujar en cualquiera de los objetos secundarios visuales.

  • Los elementos de la lista de instrucciones de gráficos vectoriales se representan de izquierda a derecha.

Árbol visual

El árbol visual contiene todos los elementos visuales usados en la interfaz de usuario de una aplicación. Dado que un elemento visual contiene información de dibujo persistente, puede pensar en el árbol visual como un gráfico de escenas, que contiene toda la información de representación necesaria para componer la salida en el dispositivo de visualización. Este árbol es la acumulación de todos los elementos visuales creados directamente por la aplicación, ya sea en el código o en el marcado. El árbol visual también contiene todos los elementos visuales creados por la expansión de plantillas de elementos como controles y objetos de datos.

El siguiente código muestra un elemento StackPanel definido en el marcado.

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

Si tuviera que enumerar los objetos visuales que componen el StackPanel elemento en el ejemplo de marcado, encontraría la jerarquía de objetos visuales que se muestra a continuación:

Diagrama de la jerarquía de árbol visual de un control StackPanel.

Orden de representación

El árbol visual determina el orden de representación de objetos visuales y de dibujo de WPF. El orden de recorrido comienza con el objeto visual raíz, que es el nodo superior del árbol visual. Los nodos secundarios del objeto visual raíz se recorren, de izquierda a derecha. Si un objeto visual tiene hijos, sus hijos se recorren antes de los hermanos del objeto visual. Esto significa que el contenido de un objeto visual secundario se representa delante del propio contenido del objeto visual.

Diagrama del orden de representación del árbol visual

Objeto visual raíz

El objeto visual raíz es el elemento superior de una jerarquía de árboles visuales. En la mayoría de las aplicaciones, la clase base del objeto visual raíz es Window o NavigationWindow. Sin embargo, si hospedaste objetos visuales en una aplicación Win32, el objeto visual raíz sería el objeto visual superior que hospedaste en la ventana Win32. Para obtener más información, vea Tutorial: Hospedaje de objetos visuales en una aplicación Win32.

Relación con el árbol lógico

El árbol lógico de WPF representa los elementos de una aplicación en tiempo de ejecución. Aunque no manipula directamente este árbol, esta vista de la aplicación es útil para comprender la herencia de propiedades y el enrutamiento de eventos. A diferencia del árbol visual, el árbol lógico puede representar objetos de datos no visuales, como ListItem. En muchos casos, el árbol lógico corresponde muy de cerca a las definiciones de marcado de una aplicación. El siguiente código muestra un elemento DockPanel definido en el marcado.

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

Si tuviera que enumerar los objetos lógicos que componen el DockPanel elemento en el ejemplo de marcado, encontraría la jerarquía de objetos lógicos que se muestra a continuación:

Diagrama de árbol
Diagrama del árbol lógico

Tanto el árbol visual como el árbol lógico se sincronizan con el conjunto actual de elementos de aplicación, lo que refleja cualquier adición, eliminación o modificación de elementos. Sin embargo, los árboles presentan vistas diferentes de la aplicación. A diferencia del árbol visual, el árbol lógico no expande el elemento de ContentPresenter un control. Esto significa que no hay una correspondencia directa uno a uno entre un árbol lógico y un árbol visual para el mismo conjunto de objetos. De hecho, invocar el método del objeto GetChildren y el método del objeto GetChild con el mismo elemento que un parámetro produce resultados diferentes.

Para obtener más información sobre el árbol lógico, vea Árboles en WPF.

Visualización del árbol visual con XamlPad

La herramienta WPF, XamlPad, proporciona una opción para ver y explorar el árbol visual que corresponde al contenido XAML definido actualmente. Haga clic en el botón Mostrar árbol visual de la barra de menús para mostrar el árbol visual. A continuación se muestra la expansión del contenido XAML en nodos de árbol visual en el panel Explorador de árboles visuales de XamlPad:

Panel Explorador de árboles visuales en XamlPad

Observe cómo los controles Label, TextBox y Button muestran una jerarquía de objetos visuales independiente en el panel Explorador de Visual Tree de XamlPad. Esto se debe a que los controles WPF tienen un ControlTemplate que contiene el árbol visual de ese control. Al hacer referencia explícitamente a un control, se hace referencia implícitamente a su jerarquía visual.

Generación de perfiles de rendimiento visual

WPF proporciona un conjunto de herramientas de generación de perfiles de rendimiento que le permiten analizar el comportamiento en tiempo de ejecución de la aplicación y determinar los tipos de optimizaciones de rendimiento que puede aplicar. La herramienta Visual Profiler proporciona una vista gráfica enriquecida de los datos de rendimiento mediante la asignación directa al árbol visual de la aplicación. En esta captura de pantalla, la sección Uso de CPU del Generador de perfiles visuales proporciona un desglose preciso del uso de un objeto de los servicios WPF, como la representación y el diseño.

Salida de pantalla de Visual Profiler
Salida de pantalla del Visual Profiler

Comportamiento de representación visual

WPF presenta varias características que afectan al comportamiento de representación de objetos visuales: gráficos en modo retenido, gráficos vectoriales y gráficos independientes del dispositivo.

Gráficos en modo retenido

Una de las claves para comprender el rol del objeto Visual es comprender la diferencia entre el modo inmediato y los sistemas gráficos de modo retenido . Una aplicación Win32 estándar basada en GDI o GDI+ usa un sistema gráfico en modo inmediato. Esto significa que la aplicación es responsable de volver a dibujar la parte del área de cliente que queda invalidada, debido a una acción tales como el cambio de tamaño de una ventana o un objeto que cambia su apariencia visual.

Diagrama de la secuencia de representación de Win32

Por el contrario, WPF usa un sistema de modo retenido. Esto significa que los objetos de aplicación que tienen una apariencia visual definen un conjunto de datos de dibujo serializados. Una vez definidos los datos de dibujo, el sistema es responsable de responder a todas las solicitudes de repintado para renderizar los objetos de la aplicación. Incluso en tiempo de ejecución, puede modificar o crear objetos de aplicación y seguir confiando en el sistema para responder a las solicitudes de pintura. La capacidad de un sistema de gráficos en modo retenido radica en que la aplicación siempre conserva la información de dibujo en un estado serializado, mientras que la responsabilidad del procesamiento se deja al sistema. En el diagrama siguiente se muestra cómo se basa la aplicación en WPF para responder a las solicitudes de pintura.

Diagrama de la secuencia de representación de WPF

Redibujado Inteligente

Una de las mayores ventajas en el uso de gráficos en modo retenido es que WPF puede optimizar eficazmente lo que necesita volver a dibujarse en la aplicación. Incluso si tiene una escena compleja con distintos niveles de opacidad, por lo general no es necesario escribir código de propósito especial para optimizar el volver a dibujar. Compárelo con la programación de Win32, donde puede invertir mucho esfuerzo en optimizar la aplicación minimizando la cantidad de repintado del área de actualización. Consulte Volver a dibujar en la región de actualización para obtener un ejemplo del tipo de complejidad implicado en la optimización del nuevo dibujo en aplicaciones Win32.

Gráficos vectoriales

WPF usa gráficos vectoriales como formato de datos de representación. Gráficos vectoriales, que incluyen gráficos vectoriales escalables (SVG), metarchivos de Windows (.wmf) y fuentes TrueType, almacenan datos de representación y lo transmiten como una lista de instrucciones que describen cómo volver a crear una imagen mediante primitivos gráficos. Por ejemplo, las fuentes TrueType son fuentes de esquema que describen un conjunto de líneas, curvas y comandos, en lugar de una matriz de píxeles. Una de las principales ventajas de los gráficos vectoriales es la capacidad de escalar a cualquier tamaño y resolución.

A diferencia de los gráficos vectoriales, los gráficos de mapa de bits almacenan datos de representación como una representación de píxel por píxel de una imagen, representada previamente para una resolución específica. Una de las principales diferencias entre los formatos de gráfico vectorial y mapa de bits es la fidelidad a la imagen de origen original. Por ejemplo, cuando se modifica el tamaño de una imagen de origen, los sistemas gráficos de mapa de bits amplían la imagen, mientras que los sistemas de gráficos vectoriales escalan la imagen, conservando la fidelidad de la imagen.

La siguiente ilustración muestra una imagen fuente cuyo tamaño se ha ajustado al 300 %%. Observe las distorsiones que aparecen cuando la imagen de origen se extiende como una imagen de gráficos de mapa de bits en lugar de escalar como una imagen de gráficos vectoriales.

Diferencias entre gráficos ráster y vector

En el marcado siguiente se muestran dos elementos Path definidos. El segundo elemento usa ScaleTransform para cambiar el tamaño de las instrucciones de dibujo del primer elemento en 300%. Observe que las instrucciones de dibujo de los Path elementos permanecen sin cambios.

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

Acerca de la resolución y los gráficos de Device-Independent

Hay dos factores del sistema que determinan el tamaño del texto y los gráficos en tu pantalla: resolución y PPP (puntos por pulgada). La resolución describe el número de píxeles que aparecen en la pantalla. A medida que la resolución aumenta, los píxeles se vuelven más pequeños, lo que hace que los gráficos y el texto aparezcan más pequeños. Un gráfico mostrado en un monitor establecido en 1024 x 768 aparecerá mucho más pequeño cuando la resolución cambie a 1600 x 1200.

La otra configuración del sistema, PPP, describe el tamaño de una pulgada de pantalla en píxeles. La mayoría de los sistemas Windows tienen un PPP de 96, lo que significa que una pulgada de pantalla es de 96 píxeles. Aumentar la configuración de PPP hace que la pulgada de pantalla sea mayor; reducir el PPP hace que la pulgada de pantalla sea más pequeña. Esto significa que una pulgada de pantalla no tiene el mismo tamaño que una pulgada real; en la mayoría de los sistemas, probablemente no. A medida que aumentas el DPI, los gráficos y el texto compatibles con DPI se vuelven más grandes porque has aumentado el tamaño de la pulgada de pantalla. Aumentar el PPP (DPI) puede hacer que el texto sea más fácil de leer, especialmente en resoluciones altas.

No todas las aplicaciones son compatibles con PPP: algunos usan píxeles de hardware como unidad de medida principal; cambiar el PPP del sistema no tiene ningún efecto en estas aplicaciones. Muchas otras aplicaciones usan unidades compatibles con PPP para describir los tamaños de fuente, pero usan píxeles para describir todo lo demás. Hacer que el PPP sea demasiado pequeño o demasiado grande puede causar problemas de diseño para estas aplicaciones, ya que el texto de las aplicaciones se escala con la configuración de PPP del sistema, pero la interfaz de usuario de las aplicaciones no. Este problema se ha eliminado para las aplicaciones desarrolladas mediante WPF.

WPF admite el escalado automático mediante el uso del píxel independiente del dispositivo como su unidad de medida principal, en lugar de píxeles de hardware; gráficos y texto se escalan correctamente sin ningún trabajo adicional del desarrollador de aplicaciones. En la ilustración siguiente se muestra un ejemplo de cómo aparecen los gráficos y el texto de WPF en diferentes configuraciones de PPP.

Gráficos y texto en diferentes configuraciones de DPI
Gráficos y texto en diferentes configuraciones de PPP

Clase VisualTreeHelper

La VisualTreeHelper clase es una clase auxiliar estática que proporciona funcionalidad de bajo nivel para programar en el nivel de objeto visual, lo que resulta útil en escenarios muy específicos, como el desarrollo de controles personalizados de alto rendimiento. En la mayoría de los casos, los objetos de marco wpF de nivel superior, como Canvas y TextBlock, ofrecen mayor flexibilidad y facilidad de uso.

Pruebas de posicionamiento

La VisualTreeHelper clase proporciona métodos para pruebas de impacto en objetos visuales cuando el soporte predeterminado para pruebas de impacto no satisface sus necesidades. Puede usar los HitTest métodos de la VisualTreeHelper clase para determinar si un valor de coordenada de geometría o punto está dentro del límite de un objeto determinado, como un control o un elemento gráfico. Por ejemplo, puede usar pruebas de posicionamiento para determinar si un clic del mouse dentro del rectángulo delimitador de un objeto se encuentra dentro de la geometría de un círculo. También puede optar por invalidar la implementación predeterminada de las pruebas de posicionamiento para realizar sus propios cálculos de pruebas de posicionamiento personalizados.

Para obtener más información sobre las pruebas de posicionamiento, vea Pruebas de posicionamiento en la capa visual.

Enumerar el árbol visual

La VisualTreeHelper clase proporciona funcionalidad para enumerar los miembros de un árbol visual. Para recuperar un elemento primario, llame al método GetParent. Para recuperar un hijo o descendiente directo de un objeto visual, llame al método GetChild. Este método devuelve un hijo Visual del padre en el índice especificado.

En el ejemplo siguiente se muestra cómo enumerar todos los descendientes de un objeto visual, que es una técnica que puede usar si le interesa serializar toda la información de representación de una jerarquía de objetos visuales.

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

En la mayoría de los casos, el árbol lógico es una representación más útil de los elementos de una aplicación WPF. Aunque no modifique el árbol lógico directamente, esta vista de la aplicación es útil para comprender la herencia de propiedades y el enrutamiento de eventos. A diferencia del árbol visual, el árbol lógico puede representar objetos de datos no visuales, como ListItem. Para obtener más información sobre el árbol lógico, vea Árboles en WPF.

La VisualTreeHelper clase proporciona métodos para devolver el rectángulo delimitador de objetos visuales. Puede devolver el rectángulo delimitador de un elemento visual llamando a GetContentBounds. Puede devolver el rectángulo delimitador de todos los descendientes de un objeto visual, incluido el propio objeto visual, llamando a GetDescendantBounds. El código siguiente muestra cómo calcularía el rectángulo delimitador de un objeto visual y todos sus descendientes.

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

Consulte también