Condividi tramite


Cenni preliminari sul rendering della grafica WPF

In questo argomento viene fornita una panoramica del livello visivo WPF. È incentrato sul ruolo della Visual classe per il supporto per il rendering nel modello WPF.

Ruolo dell'oggetto visivo

La Visual classe è l'astrazione di base da cui deriva ogni FrameworkElement oggetto. Funge anche da punto di ingresso per la scrittura di nuovi controlli in WPF e in molti modi può essere considerato come l'handle di finestra (HWND) nel modello di applicazione Win32.

L'oggetto Visual è un oggetto WPF di base, il cui ruolo primario consiste nel fornire supporto per il rendering. I controlli dell'interfaccia utente, ad esempio Button e TextBox, derivano dalla Visual classe e lo usano per rendere persistenti i dati di rendering. L'oggetto Visual fornisce il supporto per:

  • Visualizzazione dell'output: rendering del contenuto di disegno persistente e serializzato di un oggetto visivo.

  • Trasformazioni: esecuzione di trasformazioni in un oggetto visivo.

  • Ritaglio: supporto dell'area di ritaglio per un oggetto visivo.

  • Hit testing: determinare se una coordinata o una geometria è contenuta all'interno dei limiti di una visualizzazione.

  • Calcolo del rettangolo di delimitazione: determinazione del rettangolo di delimitazione di un oggetto visivo.

Tuttavia, l'oggetto Visual non include il supporto per le funzionalità non di rendering, ad esempio:

  • Gestione degli eventi

  • Impaginazione

  • Stili

  • associazione dei dati

  • Globalizzazione

Visual viene esposto come classe astratta pubblica dalle quali le classi figlio devono derivare. La figura seguente mostra la gerarchia degli oggetti visivi esposti in WPF.

Diagramma delle classi derivate dall'oggetto Visual

Classe DrawingVisual

Il DrawingVisual è una classe di disegno leggera usata per eseguire il rendering di forme, immagini o testo. Questa classe è considerata leggera perché non fornisce layout o gestione degli eventi, migliorandone le prestazioni di runtime. Per questo motivo, i disegni sono ideali per sfondi e clipart. Può DrawingVisual essere utilizzato per creare un oggetto visivo personalizzato. Per altre informazioni, vedere Using DrawingVisual Objects.

Classe Viewport3DVisual

Il Viewport3DVisual fornisce un ponte tra gli oggetti 2D Visual e Visual3D. La Visual3D classe è la classe base per tutti gli elementi visivi 3D. La Viewport3DVisual richiede che si definisca un valore Camera e un valore Viewport. La fotocamera consente di visualizzare la scena. Il riquadro di visualizzazione stabilisce dove la proiezione viene mappata sulla superficie 2D. Per altre informazioni su 3D in WPF, vedere Panoramica della grafica 3D.

Classe ContainerVisual

La ContainerVisual classe viene utilizzata come contenitore per una raccolta di Visual oggetti . La DrawingVisual classe deriva dalla ContainerVisual classe , consentendo di contenere una raccolta di oggetti visivi.

Disegno di contenuto negli oggetti visivi

Un Visual oggetto archivia i dati di rendering come elenco di istruzioni grafiche vettoriali. Ogni elemento nell'elenco di istruzioni rappresenta un set di dati grafici di basso livello e le risorse associate in un formato serializzato. Esistono quattro diversi tipi di dati di rendering che possono contenere contenuto di disegno.

Tipo di contenuto di disegno Descrizione
Grafica vettoriale Rappresenta i dati grafici vettoriali, e tutte le informazioni associate Brush e Pen.
Immagine Rappresenta un'immagine all'interno di un'area definita da un oggetto Rect.
Glifo Rappresenta un disegno che esegue il rendering di un GlyphRun, che è una sequenza di glifi da una risorsa carattere specificata. Questo è il modo in cui viene rappresentato il testo.
Video Rappresenta un disegno che genera un video.

DrawingContext consente di popolare un oggetto Visual con contenuto visivo. Quando si usano i comandi di disegno di un DrawingContext oggetto, si archivia effettivamente un set di dati di rendering che verranno usati successivamente dal sistema grafico. Non si sta disegnando sullo schermo in tempo reale.

Quando si crea un controllo WPF, ad esempio , Buttonil controllo genera in modo implicito i dati di rendering per il disegno stesso. Se ad esempio si imposta la Content proprietà dell'oggetto Button , il controllo archivia una rappresentazione di rendering di un glifo.

Un Visual oggetto descrive il contenuto come uno o più Drawing oggetti contenuti all'interno di un oggetto DrawingGroup. Un DrawingGroup oggetto descrive anche maschere di opacità, trasformazioni, effetti bitmap e altre operazioni applicate al relativo contenuto. DrawingGrouple operazioni vengono applicate nell'ordine seguente quando viene eseguito il rendering del contenuto: OpacityMask, Opacity, BitmapEffectClipGeometry, GuidelineSet, e quindi Transform.

Nella figura seguente viene illustrato l'ordine in cui DrawingGroup vengono applicate le operazioni durante la sequenza di rendering.

Ordine delle operazioni DrawingGroup
Ordine delle operazioni DrawingGroup

Per ulteriori informazioni, vedere Panoramica degli oggetti di disegno.

Disegno del contenuto a livello visivo

Non creare mai direttamente un'istanza DrawingContextdi . È tuttavia possibile acquisire un contesto di disegno da determinati metodi, ad esempio DrawingGroup.Open e DrawingVisual.RenderOpen. L'esempio seguente recupera un oggetto DrawingContext da un DrawingVisual oggetto e lo usa per disegnare un rettangolo.

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

Enumerazione del contenuto del disegno a livello visivo

Oltre agli altri usi, Drawing gli oggetti forniscono anche un modello a oggetti per enumerare il contenuto di un oggetto Visual.

Annotazioni

Quando si enumerano i contenuti del visivo, si recuperano gli oggetti Drawing e non la rappresentazione sottostante dei dati di rendering come lista di istruzioni per grafica vettoriale.

Nell'esempio seguente viene utilizzato il metodo GetDrawing per recuperare il valore DrawingGroup di un Visual ed 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.
        }
    }
}

Modalità di utilizzo degli oggetti visivi per la compilazione di controlli

Molti degli oggetti in WPF sono costituiti da altri oggetti visivi, ovvero possono contenere gerarchie variabili di oggetti discendenti. Molti degli elementi dell'interfaccia utente in WPF, ad esempio i controlli, sono costituiti da più oggetti visivi, che rappresentano diversi tipi di elementi di rendering. Ad esempio, il Button controllo può contenere diversi altri oggetti, tra cui ClassicBorderDecorator, ContentPresentere TextBlock.

Il codice seguente mostra un Button controllo definito nel markup.

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

Se si desidera enumerare gli oggetti visivi che costituiscono il controllo predefinito Button , la gerarchia degli oggetti visivi è illustrata di seguito:

Diagramma della gerarchia della struttura ad albero visuale

Il Button controllo contiene un ClassicBorderDecorator elemento, che a sua volta contiene un ContentPresenter elemento . L'elemento ClassicBorderDecorator è responsabile del disegno di un bordo e di uno sfondo per l'oggetto Button. L'elemento ContentPresenter è responsabile della visualizzazione del contenuto dell'oggetto Button. In questo caso, poiché viene visualizzato testo, l'elemento ContentPresenter contiene un TextBlock elemento . Il fatto che il Button controllo usi un ContentPresenter significa che il contenuto può essere rappresentato da altri elementi, ad esempio un Image oggetto o una geometria, ad esempio un oggetto EllipseGeometry.

Modelli di controllo

La chiave per l'espansione di un controllo in una gerarchia di controlli è .ControlTemplate Un modello di controllo specifica la gerarchia visiva predefinita per un controllo . Quando si fa riferimento in modo esplicito a un controllo, si fa riferimento implicitamente alla relativa gerarchia visiva. È possibile eseguire l'override dei valori predefiniti per un modello di controllo per creare un aspetto visivo personalizzato per un controllo. Ad esempio, è possibile modificare il valore del colore di sfondo del Button controllo in modo che usi un valore di colore sfumatura lineare anziché un valore di colore a tinta unita. Per altre informazioni, vedere Stili e modelli dei pulsanti.

Un elemento dell'interfaccia utente, ad esempio un Button controllo, contiene diversi elenchi di istruzioni grafiche vettoriali che descrivono l'intera definizione di rendering di un controllo. Il codice seguente mostra un Button controllo definito nel markup.

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

Se si desidera enumerare gli oggetti visivi e gli elenchi di istruzioni grafiche vettoriali che costituiscono il Button controllo, è possibile trovare la gerarchia degli oggetti illustrati di seguito:

Diagramma della struttura ad albero visuale e del rendering dei dati

Il Button controllo contiene un ClassicBorderDecorator elemento, che a sua volta contiene un ContentPresenter elemento . L'elemento ClassicBorderDecorator è responsabile del disegno di tutti gli elementi grafici discreti che costituiscono il bordo e lo sfondo di un pulsante. L'elemento ContentPresenter è responsabile della visualizzazione del contenuto dell'oggetto Button. In questo caso, poiché viene visualizzata un'immagine, l'elemento ContentPresenter contiene un Image elemento .

Esistono diversi punti da notare sulla gerarchia degli oggetti visivi e degli elenchi di istruzioni grafiche vettoriali:

  • L'ordinamento nella gerarchia rappresenta l'ordine di rendering delle informazioni grafiche. A partire dall'elemento visivo radice, gli elementi figli vengono attraversati da sinistra a destra e dall'alto verso il basso. Se un elemento ha elementi figli visuali, vengono attraversati prima dei suoi elementi fratelli.

  • Gli nodi non-foglia nella gerarchia, come ContentPresenter, sono utilizzati per contenere elementi figlio e non contengono elenchi di istruzioni.

  • Se un elemento visivo contiene sia un elenco di istruzioni grafiche vettoriali che elementi figlio visivi, il rendering dell'elenco di istruzioni nell'elemento visivo padre viene eseguito prima dei disegni in uno degli oggetti figlio visivi.

  • Viene eseguito il rendering degli elementi nell'elenco di istruzioni di grafica vettoriale da sinistra a destra.

Struttura ad albero visuale

La struttura ad albero visuale contiene tutti gli elementi visivi usati nell'interfaccia utente di un'applicazione. Poiché un elemento visivo contiene informazioni di disegno persistenti, è possibile considerare la struttura ad albero visuale come un grafico della scena, contenente tutte le informazioni di rendering necessarie per comporre l'output nel dispositivo di visualizzazione. Questo albero è l'accumulo di tutti gli elementi visivi creati direttamente dall'applicazione, sia nel codice che nel markup. La struttura ad albero visuale contiene anche tutti gli elementi visivi creati dall'espansione del modello di elementi, ad esempio controlli e oggetti dati.

Il codice seguente mostra un StackPanel elemento definito nel markup.

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

Se si desidera enumerare gli oggetti visivi che costituiscono l'elemento StackPanel nell'esempio di markup, la gerarchia degli oggetti visivi è illustrata di seguito:

Diagramma della gerarchia della struttura ad albero visuale di un controllo StackPanel.

Ordine di rendering

La struttura ad albero visuale determina l'ordine di rendering degli oggetti visivi e di disegno WPF. L'ordine di attraversamento inizia con l'oggetto visivo radice, ovvero il nodo più in alto nella struttura ad albero visuale. I figli dell'oggetto visivo radice vengono quindi traversati da sinistra a destra. Se un oggetto visivo ha elementi figlio, i relativi elementi figlio vengono attraversati prima degli elementi di pari livello dell'oggetto visivo. Ciò significa che il rendering del contenuto di un oggetto visivo figlio viene eseguito davanti al contenuto dell'oggetto visivo.

Diagramma dell'ordine di rendering della struttura ad albero visuale

Visuale Radice

L'elemento visivo radice è l'elemento più alto in una gerarchia di un albero visivo. Nella maggior parte delle applicazioni la classe di base dell'oggetto visivo radice è Window o NavigationWindow. Tuttavia, se si ospitavano oggetti visivi in un'applicazione Win32, l'oggetto visivo radice era l'oggetto visivo più in alto che si ospitava nella finestra Win32. Per altre informazioni, vedere Esercitazione: Hosting di oggetti visivi in un'applicazione Win32.

Relazione con l'albero logico

L'albero logico in WPF rappresenta gli elementi di un'applicazione in fase di esecuzione. Anche se non si modifica direttamente questo albero, questa visualizzazione dell'applicazione è utile per comprendere l'ereditarietà delle proprietà e il routing degli eventi. A differenza della struttura ad albero visuale, l'albero logico può rappresentare oggetti dati non visivi, ad esempio ListItem. In molti casi, l'albero logico corrisponde strettamente alle definizioni di markup di un'applicazione. Il codice seguente mostra un DockPanel elemento definito nel markup.

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

Se si desidera enumerare gli oggetti logici che costituiscono l'elemento DockPanel nell'esempio di markup, la gerarchia degli oggetti logici è illustrata di seguito:

Diagramma ad albero
Diagramma dell'albero logico

Sia la struttura ad albero visuale che la struttura ad albero logica vengono sincronizzate con il set corrente di elementi dell'applicazione, riflettendo eventuali aggiunte, eliminazioni o modifiche degli elementi. Tuttavia, gli alberi presentano visualizzazioni diverse dell'applicazione. A differenza della struttura ad albero visuale, l'albero logico non espande l'elemento ContentPresenter di un controllo. Ciò significa che non esiste una corrispondenza uno-a-uno diretta tra un albero logico e una struttura ad albero visuale per lo stesso set di oggetti. In effetti, richiamando il metodo dell'oggetto LogicalTreeHelper e il metodo dell'oggetto GetChildren usando lo stesso elemento come parametro, si ottengono risultati diversi.

Per altre informazioni sull'albero logico, vedere Trees in WPF.

Visualizzazione della struttura ad albero visuale con XamlPad

Lo strumento WPF, XamlPad, offre un'opzione per visualizzare ed esplorare la struttura ad albero visuale corrispondente al contenuto XAML attualmente definito. Fare clic sul pulsante Mostra struttura ad albero visuale sulla barra dei menu per visualizzare la struttura ad albero visuale. Di seguito viene illustrata l'espansione del contenuto XAML nei nodi della struttura ad albero visuale nel pannello Esplora albero visuale di XamlPad:

Pannello Esploratore dell'albero visivo in XamlPad

Si noti che i controlli Label, TextBox e Button visualizzano ciascuno una gerarchia separata di oggetti visivi nel pannello Esplora albero visivo di XamlPad. Ciò è dovuto al fatto che i controlli WPF dispongono di un oggetto ControlTemplate che contiene la struttura ad albero visuale di tale controllo. Quando si fa riferimento in modo esplicito a un controllo, si fa riferimento implicitamente alla relativa gerarchia visiva.

Profilatura delle prestazioni visive

WPF offre una suite di strumenti di profilatura delle prestazioni che consentono di analizzare il comportamento di runtime dell'applicazione e determinare i tipi di ottimizzazioni delle prestazioni che è possibile applicare. Lo strumento Visual Profiler offre una visualizzazione grafica avanzata dei dati sulle prestazioni eseguendo direttamente il mapping alla struttura ad albero visuale dell'applicazione. In questo screenshot, la sezione Utilizzo CPU di Visual Profiler offre una suddivisione precisa dell'uso di servizi WPF di un oggetto, ad esempio rendering e layout.

Output della visualizzazione di Visual Profiler
Risultato di visualizzazione del Visual Profiler

Comportamento di rendering visivo

WPF introduce diverse funzionalità che influiscono sul comportamento di rendering degli oggetti visivi: grafica in modalità mantenuta, grafica vettoriale e grafica indipendente dal dispositivo.

Grafica in modalità mantenuta

Una delle chiavi per comprendere il ruolo dell'oggetto Visual consiste nel comprendere la differenza tra la modalità immediata e i sistemi grafici in modalità mantenuta . Un'applicazione Win32 standard basata su GDI o GDI+ usa un sistema grafico in modalità immediata. Ciò significa che l'applicazione è responsabile di ridipingere la parte dell'area client invalidata, a causa di un'azione come il ridimensionamento di una finestra o di un oggetto che modifica l'aspetto visivo.

Diagramma della sequenza di rendering Win32

Al contrario, WPF utilizza un sistema a modalità mantenuta. Ciò significa che gli oggetti applicazione con un aspetto visivo definiscono un set di dati di disegno serializzati. Dopo aver definito i dati di disegno, il sistema è successivamente responsabile di rispondere a tutte le richieste di ridisegno per il rendering degli oggetti dell'applicazione. Anche in fase di esecuzione, è possibile modificare o creare oggetti applicazione e basarsi comunque sul sistema per rispondere alle richieste di disegno. La potenza di un sistema grafico in modalità mantenuta risiede nel fatto che le informazioni di disegno vengono sempre mantenute in uno stato serializzato dall'applicazione, mentre la responsabilità del rendering è affidata al sistema. Il diagramma seguente illustra come l'applicazione si basa su WPF per rispondere alle richieste di disegno.

Diagramma della sequenza di rendering WPF

Ridisegno intelligente

Uno dei principali vantaggi dell'uso della grafica in modalità mantenuta è che WPF può ottimizzare in modo efficiente ciò che deve essere ridisegnato nell'applicazione. Anche se si dispone di una scena complessa con diversi livelli di opacità, in genere non è necessario scrivere codice speciale per ottimizzare il ridisegno. Confrontare questo comportamento con la programmazione Win32 in cui è possibile dedicare molto lavoro per ottimizzare l'applicazione riducendo al minimo la quantità di ridisegno nell'area di aggiornamento. Vedi Ridisegno nell'area di aggiornamento per un esempio del tipo di complessità coinvolto nell'ottimizzazione del ridisegno nelle applicazioni Win32.

Grafica vettoriale

WPF usa la grafica vettoriale come formato di dati di rendering. Grafica vettoriale, che includono svg (Scalable Vector Graphics), metafile Windows (wmf) e tipi di carattere TrueType, archiviano i dati di rendering e li trasmettono come un elenco di istruzioni che descrivono come ricreare un'immagine usando primitive grafiche. Ad esempio, i caratteri TrueType sono font a contorno che descrivono un insieme di linee, curve e comandi, anziché una matrice di pixel. Uno dei vantaggi principali della grafica vettoriale è la possibilità di ridimensionare in qualsiasi dimensione e risoluzione.

A differenza della grafica vettoriale, la grafica bitmap memorizza i dati di rendering come rappresentazione punto per punto di un'immagine, predisposta per il rendering a una risoluzione specifica. Una delle differenze principali tra i formati grafici bitmap e vettoriali è fedele all'immagine di origine originale. Ad esempio, quando vengono modificate le dimensioni di un'immagine di origine, i sistemi grafici bitmap estendono l'immagine, mentre i sistemi grafici vettoriali ridimensionano l'immagine, mantenendo la fedeltà dell'immagine.

La figura seguente mostra un'immagine di origine ridimensionata da 300%. Si notino le distorsioni visualizzate quando l'immagine di origine viene estesa come immagine grafica bitmap anziché ridimensionata come immagine grafica vettoriale.

Differenze tra grafica raster e vettoriale

Il markup seguente mostra due Path elementi definiti. Il secondo elemento utilizza ScaleTransform per ridimensionare le istruzioni di disegno del primo elemento di 300%. Si noti che le istruzioni di disegno negli Path elementi rimangono invariate.

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

Informazioni sulla risoluzione e sulla grafica Device-Independent

Esistono due fattori di sistema che determinano le dimensioni del testo e della grafica sullo schermo: risoluzione e DPI. La risoluzione descrive il numero di pixel visualizzati sullo schermo. Man mano che la risoluzione aumenta, i pixel diventano più piccoli, causando la visualizzazione di grafica e testo più piccoli. Un grafico visualizzato su un monitor impostato su 1024 x 768 apparirà molto più piccolo quando la risoluzione viene modificata in 1600 x 1200.

L'altra impostazione di sistema, DPI, descrive le dimensioni di un pollice dello schermo in pixel. La maggior parte dei sistemi Windows ha un VALORE DPI pari a 96, il che significa che un pollice dello schermo è di 96 pixel. L'aumento dell'impostazione DPI rende più grande il pollice dello schermo; riducendo il DPI rende più piccolo il pollice dello schermo. Ciò significa che un pollice dello schermo non è la stessa dimensione di un pollice reale; nella maggior parte dei sistemi, probabilmente non è. Man mano che si aumenta il valore DPI, la grafica e il testo compatibili con DPI diventano più grandi perché sono state aumentate le dimensioni del pollice dello schermo. L'aumento del dpi può rendere il testo più facile da leggere, soprattutto a risoluzioni elevate.

Non tutte le applicazioni sono compatibili con DPI: alcuni usano i pixel hardware come unità di misura primaria; la modifica del dpi di sistema non ha alcun effetto su queste applicazioni. Molte altre applicazioni usano unità compatibili con DPI per descrivere le dimensioni del carattere, ma usano i pixel per descrivere tutto il resto. La riduzione della dpi troppo piccola o troppo grande può causare problemi di layout per queste applicazioni, perché il testo delle applicazioni viene ridimensionato con l'impostazione DPI del sistema, ma l'interfaccia utente delle applicazioni non lo fa. Questo problema è stato eliminato per le applicazioni sviluppate con WPF.

WPF supporta il ridimensionamento automatico usando il pixel indipendente dal dispositivo come unità di misura principale, anziché i pixel hardware; grafica e scalabilità del testo correttamente senza alcun lavoro aggiuntivo da parte dello sviluppatore di applicazioni. La figura seguente mostra un esempio di come vengono visualizzati testo e grafica WPF in impostazioni DPI diverse.

Grafica e testo in impostazioni DPI diverse
Grafica e testo in impostazioni DPI diverse

Classe VisualTreeHelper

La VisualTreeHelper classe è una classe helper statica che fornisce funzionalità di basso livello per la programmazione a livello di oggetto visivo, utile in scenari molto specifici, ad esempio lo sviluppo di controlli personalizzati ad alte prestazioni. Nella maggior parte dei casi, gli oggetti framework WPF di livello superiore, ad esempio Canvas e TextBlock, offrono maggiore flessibilità e facilità d'uso.

Test di collisione

La VisualTreeHelper classe fornisce metodi per l'hit testing sugli oggetti visivi quando il supporto di hit test predefinito non soddisfa le proprie esigenze. È possibile utilizzare i HitTest metodi nella VisualTreeHelper classe per determinare se un valore di coordinata geometry o punto si trova all'interno del limite di un determinato oggetto, ad esempio un controllo o un elemento grafico. Ad esempio, è possibile usare hit testing per determinare se un clic del mouse all'interno del rettangolo di delimitazione di un oggetto rientra nella geometria di un cerchio È anche possibile scegliere di eseguire l'override dell'implementazione predefinita di hit test per eseguire calcoli personalizzati di hit test.

Per ulteriori informazioni su hit testing, vedere Hit Testing nello strato visivo.

Enumerazione dell'albero visivo

La VisualTreeHelper classe fornisce funzionalità per enumerare i membri di una struttura ad albero visuale. Per recuperare un elemento padre, chiamare il metodo GetParent. Per recuperare un figlio o un discendente diretto di un oggetto visivo, chiamare il metodo GetChild. Questo metodo restituisce un elemento figlio Visual dell'elemento padre in corrispondenza dell'indice specificato.

Nell'esempio seguente viene illustrato come enumerare tutti i discendenti di un oggetto visivo, ovvero una tecnica da usare se si è interessati a serializzare tutte le informazioni di rendering di una gerarchia di oggetti visivi.

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

Nella maggior parte dei casi, l'albero logico è una rappresentazione più utile degli elementi in un'applicazione WPF. Anche se non si modifica direttamente l'albero logico, questa visualizzazione dell'applicazione è utile per comprendere l'ereditarietà delle proprietà e il routing degli eventi. A differenza della struttura ad albero visuale, l'albero logico può rappresentare oggetti dati non visivi, ad esempio ListItem. Per altre informazioni sull'albero logico, vedere Trees in WPF.

La VisualTreeHelper classe fornisce metodi per restituire il rettangolo di delimitazione degli oggetti visivi. È possibile restituire il rettangolo di delimitazione di un oggetto visivo chiamando GetContentBounds. È possibile restituire il rettangolo di delimitazione di tutti i discendenti di un oggetto visivo, incluso l'oggetto visivo stesso, chiamando GetDescendantBounds. Il codice seguente illustra come calcolare il rettangolo di delimitazione di un oggetto visivo e tutti i relativi discendenti.

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

Vedere anche