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

En este tema se ofrece información general sobre la capa de objeto visual de WPF. Se centra en el rol de la clase Visual para representar la compatibilidad en el modelo de WPF.

Rol del objeto visual

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

El objeto Visual es un objecto WPF de núcleo cuyo rol principal es proporcionar asistencia con la representación. Los controles de interfaz de usuario, como Button y TextBox derivan de la clase Visual y la usan para continuar la representación de datos. El objeto Visual proporciona compatibilidad con:

  • Presentación de salida: representación persistente, serializa el contenido de dibujo de un objeto visual.

  • Transformaciones: realizar transformaciones en un objeto visual.

  • Recorte: proporcionar soporte para una zona de recorte de un objeto visual.

  • Pruebas de posicionamiento: determinar si una coordenada o geometría está dentro de los límites de un objeto visual.

  • Cálculos de rectángulo de selección: determinar el rectángulo delimitador de un objeto visual.

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

  • Control de eventos

  • Layout

  • Estilos

  • Enlace de datos

  • Globalización

Visual se expone como una clase abstracta pública de la que se deben derivar clases secundarias. La siguiente ilustración 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 utiliza para representar formas, imágenes o texto. Esta clase se considera ligera porque no proporciona control de 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 e imágenes prediseñadas. DrawingVisual se puede usar para crear un objeto visual personalizado. Para más información, consulte Usar objetos DrawingVisual.

Clase Viewport3DVisual

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

Clase ContainerVisual

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

Dibujo de contenido en objetos visuales

Un objeto Visual 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 bajo nivel de datos gráficos y recursos asociados en un formato serializado. Hay cuatro tipos diferentes de datos de representación que pueden incluir contenido de dibujo.

Tipo de contenido de dibujo Descripción
Gráficos vectoriales Representa datos de gráficos vectoriales, y cualquier información Brush y Pen asociada.
Imagen Representa una imagen dentro de una región definida por una propiedad Rect.
Glifo Representa un dibujo que representa una clase 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 representa vídeo.

DrawingContext le permite propagar Visual con contenido visual. Cuando se usan los comandos de dibujo del objeto DrawingContext, en realidad se está almacenando un conjunto de datos de representación que el sistema de gráficos utilizará más adelante; no se dibuja en la pantalla en tiempo real.

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

Visual describe su contenido como uno o más objetos Drawing contenidos en un DrawingGroup. DrawingGroup también describe las máscaras de opacidad, las transformaciones, los efectos de imagen y otras operaciones que se aplican a su contenido. Las operaciones DrawingGroup 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 se aplican las operaciones de DrawingGroup durante la secuencia de representación.

Orden de las operaciones de DrawingGroup
Orden de las operaciones de DrawingGroup

Para más información, consulte Información general sobre objetos Drawing.

Contenido de dibujo en la capa de Visual

Nunca se crea una instancia de DrawingContext directamente; sin embargo, puede adquirir un contexto de dibujo de determinados métodos, como DrawingGroup.Open y DrawingVisual.RenderOpen. En el ejemplo siguiente se recupera 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

Enumeración de contenido de dibujo en la capa de Visual

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

Nota

Cuando se enumera el contenido del objeto visual, se recuperan objetos Drawing, no la representación subyacente de los datos de representación como una lista de instrucciones de gráficos vectoriales.

En el ejemplo siguiente se usa el método GetDrawing para recuperar el valor DrawingGroup de 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.
        }
    }
}

Uso de los objetos visuales para compilar controles

Muchos de los objetos de WPF están formados por otros objetos visuales, lo que significa que pueden contener diversas jerarquías de objetos descendientes. Muchos de los elementos de la interfaz de usuario de WPF, como los controles, constan de varios objetos visuales, que representan diferentes tipos de representación de elementos. Por ejemplo, el control Button puede contener una serie de otros objetos, incluidos ClassicBorderDecorator, ContentPresenter y TextBlock.

En el código siguiente se muestra un control Button definido en el marcado.

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

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

Diagrama de jerarquía de árbol visual

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

Plantillas de control

La clave para la expansión de un control en una jerarquía de controles es ControlTemplate. Una plantilla de control especifica la jerarquía visual predeterminada de un control. Al hacer referencia explícitamente a un control, implícitamente también se hace referencia a su jerarquía visual. Puede reemplazar los valores predeterminados de una plantilla de control para crear una apariencia visual personalizada para un control. Por ejemplo, puede modificar el valor del color de fondo del control Button para que utilice un valor de color de degradado lineal, en lugar de un valor de color sólido. Para más información, consulte Button ControlTemplate Example (Ejemplo de ControlTemplate de Button).

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

<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 constituyen el control Button, encontraría la jerarquía de objetos que se ilustra a continuación:

Diagrama de árbol visual y datos de representación

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

Hay que tener en cuenta varios aspectos de la jerarquía de objetos visuales y las listas de instrucciones de gráficos vectoriales:

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

  • Los elementos del nodo no hoja de la jerarquía, como ContentPresenter, se usan para albergar 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 que los dibujos en cualquiera de los objetos visuales secundarios.

  • 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 que se usan en la interfaz de usuario de una aplicación. Puesto que un elemento visual contiene información guardada del dibujo, el árbol visual se puede considerar un gráfico de la escena, que contiene toda la información de representación necesaria para componer la salida de la pantalla. Este árbol es la acumulación de todos los elementos visuales creados directamente por la aplicación, ya sea a través de código o de marcación. El árbol visual también contiene todos los elementos visuales que ha creado la expansión de la plantilla de elementos, como controles y objetos de datos.

En el código siguiente se 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 constituyen el elemento StackPanel del ejemplo de marcación, encontraría la jerarquía de objetos visuales que se ilustra a continuación:

Diagrama de 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 del recorrido comienza con el objeto visual raíz, que es el nodo de nivel superior del árbol visual. A continuación, se atraviesan los elementos secundarios del objeto visual raíz, de izquierda a derecha. Si un objeto visual tiene elementos secundarios, estos se atraviesan antes que los elementos del mismo nivel del objeto visual. Esto significa que el contenido de un objeto visual secundario se representa delante del contenido propio del objeto visual.

Diagrama de orden de representación de árbol visual

Objeto visual raíz

El objeto visual raíz es el elemento de nivel superior de una jerarquía de árbol visual. En la mayoría de las aplicaciones, la clase base del objeto visual raíz es Window o NavigationWindow. Sin embargo, si se hospedaran objetos visuales en una aplicación Win32, el objeto visual raíz sería el objeto visual de nivel superior que se hospeda en la ventana de Win32. Para más información, consulte Tutorial: Hosting Visual Objects in a Win32 Application (Tutorial: hospedar 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 entender 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 se asigna muy estrechamente con las definiciones de marcación de una aplicación. En el código siguiente se 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 constituyen el elemento DockPanel del ejemplo de marcación, encontraría la jerarquía de objetos lógicos que se ilustra a continuación:

Diagrama de árbol
Diagrama de árbol lógico

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

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

Visualización del árbol visual con XamlPad

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

Panel del explorador de árbol visual en XamlPad

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

Generación de perfiles de rendimiento visual

WPF ofrece 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 Generador de perfiles visuales proporciona una vista gráfica completa de los datos de rendimiento mediante la asignación 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 que un objeto realiza de los servicios de WPF, como la representación y el diseño.

Resultado mostrado del generador de perfiles visuales
Resultados del generador de perfiles visuales

Comportamiento de la representación visual

WPF presenta varias características que afectan al comportamiento de la representación de los 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 conocer el rol del objeto visual es conocer la diferencia entre los sistemas de gráficos del modo inmediato y del modo retenido. Una aplicación Win32 estándar basada en GDI o GDI + utiliza un sistema de gráficos de modo inmediato. Esto significa que la aplicación es responsable de volver a dibujar la parte del área de cliente que se ha invalidado, debido a una acción, como el cambio de tamaño de una ventana o al cambio de la apariencia visual de un objeto.

Diagrama de secuencia de representación de Win32

En cambio, WPF utiliza un sistema de modo retenido. Esto significa que los objetos de la aplicación que tienen una apariencia visual definen un conjunto de datos de dibujo serializados. Una vez que se definen los datos de dibujo, el sistema es responsable de responder a todas las solicitudes de repetición del dibujo para representar los objetos de la aplicación. Incluso en tiempo de ejecución, puede modificar o crear objetos de la aplicación y seguir confiando en que el sistema responderá a las solicitudes de dibujo. La eficacia de un sistema de gráficos en modo retenido es que la aplicación guarda siempre la información de dibujo en un estado serializado, pero la responsabilidad de la representación se deja al sistema. El siguiente diagrama muestra la forma en que la aplicación usa WPF para responder a las solicitudes de dibujo.

Diagrama de secuencia de representación de WPF

Volver a dibujar de forma inteligente

Una de las mayores ventajas de utilizar gráficos en modo retenido es que WPF puede optimizar eficazmente lo que hay que volver a dibujar en la aplicación. Aunque tenga una escena compleja con diferentes niveles de opacidad, por lo general no es preciso escribir código especial para optimizar el redibujado. Compárelo esto con la programación de Win32, en la que se puede dedicar mucho esfuerzo a optimizar la aplicación mediante la minimización de la cantidad de redibujado que se realiza en la región de actualización. Consulte Redrawing in the Update Region (Redibujado en la región de actualización) para obtener un ejemplo del tipo de complejidad implicado en la optimización del redibujado en las aplicaciones de Win32.

Gráficos vectoriales

WPF usa gráficos vectoriales como formato de los datos de representación. Los gráficos vectoriales, que incluyen Scalable Vector Graphics (SVG), metarchivos de Windows (.wmf) y fuentes TrueType, almacenan datos de representación y los transmiten como una lista de instrucciones que describen cómo volver a crear una imagen mediante primitivas de 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 ventajas principales de los gráficos vectoriales es su capacidad para escalar a cualquier tamaño y resolución.

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

La ilustración siguiente muestra una imagen de origen cuyo tamaño se ha cambiado en un 300 %. Observe las distorsiones que aparecen cuando la imagen de origen es un gráfico de mapa de bits y se ajusta, en lugar de escalarse como imagen de gráfico vectorial.

Diferencias entre gráficos de trama y vectoriales

El marcado siguiente muestra dos elementos Path definidos. El segundo elemento utiliza ScaleTransform para cambiar el tamaño de las instrucciones de dibujo del primer elemento en un 300 %. Observe que las instrucciones de dibujo de los elementos Path 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 los gráficos independientes de la resolución y del dispositivo

Hay dos factores del sistema que determinan el tamaño tanto del texto como de los gráficos en la pantalla: la resolución y los puntos por pulgada. La resolución describe el número de píxeles que aparecen en la pantalla. A medida que aumenta la resolución, disminuye el tamaño de los píxeles, lo que provoca que tanto los gráficos como el texto parezcan menores. Un gráfico que se muestre en un monitor cuya resolución se haya configurado en 1024 x 768 píxeles parecerá mucho más pequeño cuando dicha resolución se cambie a 1600 x 1200.

La otra configuración del sistema, los puntos por pulgada (ppp), describe el tamaño de una pulgada de pantalla, en píxeles. La mayoría de los sistemas Windows tienen un valor de PPP de 96, lo que significa que una pulgada de la pantalla tiene 96 píxeles. El aumento de la configuración de PPP aumenta el tamaño de la pulgada de la pantalla; mientras que su disminución lo reduce, lo que significa que una pulgada de la pantalla no es el mismo tamaño que una pulgada real; en la mayoría de los sistemas, es probable que no lo sea. A medida que se aumente el valor de PPP, tanto el texto como los gráficos con reconocimiento de PPP serán mayores, ya que se ha incrementado el tamaño de la pulgada de pantalla. El aumento del valor de PPP puede facilitar la lectura del texto, especialmente en resoluciones altas.

No todas las aplicaciones reconocen el PPP: algunas utilizan los píxeles de hardware como unidad de medida principal; por consiguiente, el cambio de los PPP del sistema no tiene ningún efecto en dichas aplicaciones. Muchas otras aplicaciones utilizan unidades con reconocimiento de PPP para describir los tamaños de fuente, pero usan píxeles para describir todo lo demás. Un valor de PPP es demasiado pequeño o demasiado grande puede provocar problemas de diseño en estas aplicaciones, ya que el texto de las aplicaciones se escala con la configuración de PPP del sistema, mientras que su interfaz de usuario no lo hace. Este problema se ha eliminado en las aplicaciones desarrolladas mediante WPF.

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

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

Clase VisualTreeHelper

La clase VisualTreeHelper es una clase del asistente estática que proporciona funcionalidad de bajo nivel para la programación en el nivel de objeto visual, lo que resulta útil en escenarios muy concretos, como el desarrollo de controles personalizados de alto rendimiento. En la mayoría de los casos, los objetos de fotograma de WPF de nivel superior, como Canvas y TextBlock, ofrecen una mayor flexibilidad y facilidad de uso.

Pruebas de posicionamiento

La clase VisualTreeHelper proporciona métodos para las pruebas de posicionamiento en objetos visuales cuando la compatibilidad con pruebas de posicionamiento predeterminada no cubre sus necesidades. Puede usar los métodos HitTest de la clase VisualTreeHelper para determinar si una geometría o un valor de coordenadas de punto está dentro del límite de un objeto dado, como un control o un elemento gráfico. Por ejemplo, las pruebas de posicionamiento se pueden utilizar para determinar si un clic del mouse dentro del rectángulo delimitador de un objeto pertenece a la geometría de un círculo. También puede elegir invalidar la implementación predeterminada de las pruebas de posicionamiento para realizar sus propios cálculos de las pruebas de posicionamiento.

Para más información acerca de las pruebas de posicionamiento, consulte Hit Testing in the Visual Layer (Pruebas de posicionamiento en la capa visual).

Enumeración del árbol visual

La clase VisualTreeHelper proporciona la funcionalidad necesaria para enumerar los miembros de un árbol visual. Para recuperar un elemento primario, llame al método GetParent. Para recuperar un elemento secundario o un descendiente directo de un objeto visual, llame al método GetChild. Este método devuelve un elemento secundario Visual del elemento primario 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 se puede utilizar si se desea 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 de WPF. Aunque no se modifique directamente el árbol lógico, esta vista de la aplicación es útil para entender 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, consulte Árboles en WPF.

La clase VisualTreeHelper proporciona métodos para devolver el rectángulo delimitador de objetos visuales. Para devolver el rectángulo delimitador de un objeto visual, llame a GetContentBounds. Para devolver el rectángulo delimitador de todos los descendientes de un objeto visual, incluido el propio objeto visual, llame a GetDescendantBounds. El código siguiente muestra cómo se 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