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: eseguire il rendering del contenuto del disegno serializzato e salvato in modo permanente di un oggetto visivo.

  • Trasformazioni: eseguire trasformazioni su un oggetto visivo.

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

  • Hit testing: determinare se una coordinata o una geometria è contenuta all'interno di un oggetto visivo.

  • Calcoli relativi al rettangolo di selezione: determinare il rettangolo delimitatore di un oggetto visivo.

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

  • Gestione degli eventi

  • Layout

  • Stili

  • Data binding

  • Globalizzazione

Visual viene esposto come classe astratta pubblica da cui devono essere derivate le classi figlio. La figura seguente mostra la gerarchia degli oggetti visivi esposti in WPF.

Diagram of classes derived from the Visual object

Classe DrawingVisual

DrawingVisual è una classe di disegno leggera utilizzata per eseguire il rendering di forme, immagini o testo. Questa classe è considerata semplice perché non offre la gestione di layout o eventi, che migliora 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 Uso degli oggetti DrawingVisual.

Classe Viewport3DVisual

fornisce Viewport3DVisual un ponte tra 2D Visual e Visual3D oggetti. La Visual3D classe è la classe base per tutti gli elementi visivi 3D. È Viewport3DVisual necessario definire un Camera valore e un Viewport valore. La camera consente di visualizzare la scena. Il viewport stabilisce dove viene eseguito il mapping della proiezione 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.

Contenuto del disegno in 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 risorse associate in un formato serializzato. Esistono quattro diversi tipi di dati di rendering che possono contenere il contenuto del disegno.

Tipo di contenuto del disegno Descrizione
Grafica vettoriale Rappresenta i dati grafici vettoriali e qualsiasi Brush informazione associata Pen .
Immagine Rappresenta un'immagine all'interno di un'area definita da un oggetto Rect.
Icona Rappresenta un disegno che esegue il rendering di un GlyphRunoggetto , ovvero una sequenza di glifi da una risorsa del tipo di carattere specificata. Ecco come viene rappresentato il testo.
Video Rappresenta un disegno che esegue il rendering di 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.

DrawingGroup order of operations
Ordine delle operazioni DrawingGroup

Per altre informazioni, vedere Cenni preliminari sugli oggetti Drawing.

Contenuto del disegno 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.

Nota

Quando si enumera il contenuto dell'oggetto visivo, si recuperano Drawing oggetti e non la rappresentazione sottostante dei dati di rendering come elenco di istruzioni grafiche vettoriali.

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

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

Diagram of visual tree hierarchy

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 in modo implicito alla relativa gerarchia visiva. È possibile eseguire l'override dei valori predefiniti di 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 di Button.

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:

Diagram of visual tree and rendering data

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 .

Tenere in considerazione alcuni punti sulla gerarchia degli oggetti visivi e sugli elenchi di istruzioni di grafica vettoriale:

  • L'ordinamento nella gerarchia rappresenta l'ordine di rendering delle informazioni di disegno. A partire dall'elemento visivo radice, gli elementi figlio vengono attraversati da sinistra a destra e dall'alto verso il basso. Se un elemento contiene elementi visivi figlio, essi vengono attraversati prima degli elementi di pari livello.

  • Gli elementi del nodo non foglia nella gerarchia, ad esempio ContentPresenter, vengono usati per contenere elementi figlio, non contengono elenchi di istruzioni.

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

  • Il rendering degli elementi nell'elenco di istruzioni di grafica vettoriale viene eseguito 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 sul disegno salvate in modo permanente, la struttura ad albero visuale può essere considerata come un grafico della scena, contenente tutte le informazioni di rendering necessarie per comporre l'output verso il dispositivo di visualizzazione. Questo albero è costituito da tutti gli elementi visivi creati direttamente dall'applicazione, nel codice o nel markup. La struttura ad albero visuale contiene anche tutti gli elementi visivi creati dall'espansione del modello di elementi quali 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:

Diagram of visual tree hierarchy of a StackPanel control.

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 superiore nella struttura ad albero visuale. Gli elementi figlio dell'oggetto visivo radice vengono quindi attraversati, da sinistra a destra. Se un oggetto visivo ha elementi figlio, questi ultimi vengono attraversati prima degli elementi di pari livello. Ciò significa che viene eseguito il rendering del contenuto di un oggetto visivo figlio prima del contenuto dell'oggetto visivo stesso.

Diagram of the visual tree rendering order

Oggetto visivo radice

L'oggetto visivo radice è l'elemento di primo livello di una gerarchia struttura ad albero visuale. Nella maggior parte delle applicazioni la classe di base dell'oggetto visivo radice è Window o NavigationWindow. Se venissero tuttavia ospitati oggetti visivi in un'applicazione Win32, l'oggetto visivo radice sarebbe l'oggetto visivo di primo livello ospitato 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. Sebbene questo albero non venga modificato direttamente, la 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 dell'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:

Tree diagram
Diagramma dell'albero logico

La struttura ad albero visuale e l'albero logico sono sincronizzati con il set corrente di elementi dell'applicazione che riflette qualsiasi aggiunta, eliminazione o modifica di elementi. Presentano tuttavia visualizzazioni diverse dell'applicazione. A differenza della struttura ad albero visuale, l'albero logico non espande l'elemento di ContentPresenter un controllo. Ciò significa che non vi è una corrispondenza diretta tra un albero logico e una struttura ad albero visuale per lo stesso set di oggetti. In effetti, richiamando il metodo dell'oggetto GetChildren LogicalTreeHelper e il metodo dell'oggetto VisualTreeHelper usando lo stesso elemento di GetChild un parametro restituisce risultati diversi.

Per altre informazioni sull'albero logico, vedere Strutture ad albero 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 Show Visual Tree (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:

Visual Tree Explorer panel in XamlPad

Si noti che i Labelcontrolli , TextBoxe Button visualizzano ogni gerarchia di oggetti visivi separati nel pannello Esplora albero visuale 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 in modo implicito 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 completa dei dati sulle prestazioni eseguendo il mapping direttamente 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.

Visual Profiler display output
Output di 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à differita

Uno dei fattori chiave per comprendere il ruolo dell'oggetto visivo consiste nel comprendere la differenza tra i sistemi di grafica in modalità immediata e in modalità differita. Un'applicazione Win32 standard basata su GDI o GDI+ usa un sistema di grafica in modalità immediata. Ciò significa che l'applicazione è responsabile dell'aggiornamento della porzione dell'area client invalidata, a causa di un'azione, ad esempio il ridimensionamento di una finestra o la modifica dell'aspetto visivo di un oggetto.

Diagram of Win32 rendering sequence

Al contrario, WPF usa un sistema in modalità mantenuta. Questo significa che gli oggetti applicazione che hanno un aspetto visivo definiscono un set di dati di disegno serializzato. Dopo aver definito i dati di disegno, il sistema è responsabile della successiva risposta a tutte le richieste di aggiornamento per il rendering degli oggetti applicazione. Anche in fase di esecuzione, è possibile modificare o creare oggetti applicazione e affidarsi al sistema per rispondere alle richieste di aggiornamento. Il punto forte di un sistema di grafica in modalità differita è che le informazioni sul disegno vengono sempre salvate in modo permanente in uno stato serializzato dall'applicazione, ma la responsabilità del rendering viene lasciata al sistema. Il diagramma seguente illustra come l'applicazione si basa su WPF per rispondere alle richieste di disegno.

Diagram of WPF rendering sequence

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 ha a che fare con una scena complessa con livelli di opacità variabili, in genere non è necessario scrivere un codice specifico per ottimizzare il ridisegno. Confrontare questo aspetto con la programmazione Win32 in cui può succedere di dedicare un notevole impegno per ottimizzare l'applicazione riducendo al minimo la quantità di ridisegno nell'area di aggiornamento. Vedere Ridisegno nell'area di aggiornamento per un esempio del tipo di complessità inclusa nell'ottimizzazione del ridisegno nelle applicazioni Win32.

Grafica vettoriale

WPF usa la grafica vettoriale come formato di dati di rendering. Le immagini vettoriali, che includono Scalable Vector Graphics (con estensione svg), Windows Metafile (con estensione wmf) e i tipi di carattere TrueType, archiviano i dati di rendering e li trasmettono come un elenco di istruzioni che descrivono come ricreare un'immagine mediante primitive grafiche. I tipi di carattere TrueType sono ad esempio caratteri vettoriali che descrivono un set di linee, curve e comandi, anziché una matrice di pixel. Uno dei principali vantaggi della grafica vettoriale è la possibilità di adattarsi a qualsiasi dimensione e risoluzione.

A differenza delle immagini vettoriali, le immagini bitmap archiviano i dati di rendering come rappresentazione pixel per pixel di un'immagine, di cui è stato eseguito il pre-rendering per una risoluzione specifica. Una delle differenze principali tra i formati di immagini bitmap e vettoriali è la fedeltà all'immagine originale. Quando ad esempio viene modificata la dimensione di un'immagine di origine, i sistemi di grafica bitmap allungano l'immagine, mentre i sistemi di grafica vettoriale la ridimensionano, conservandone la fedeltà.

La figura seguente illustra un'immagine di origine che è stata ridimensionata del 300%. Si notino le distorsioni visualizzate quando l'immagine di origine viene allungata come immagine bitmap anziché ridimensionata come immagine vettoriale.

Differences between raster and vector graphics

Il markup seguente mostra due Path elementi definiti. Il secondo elemento utilizza un oggetto ScaleTransform per ridimensionare le istruzioni di disegno del primo elemento del 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 grafica indipendente dalla risoluzione e dal dispositivo

Esistono due fattori di sistema che determinano la dimensione del testo e della grafica sullo schermo: risoluzione e DPI. La risoluzione indica il numero di pixel visualizzati sullo schermo. Con l'aumento della risoluzione i pixel vengono rimpiccioliti, con la conseguente riduzione della dimensione di grafica e testo. Un'immagine visualizzata su un monitor impostato su 1024 x 768 apparirà molto più piccola quando viene modificata la risoluzione in 1600 x 1200.

L'altra impostazione di sistema, DPI, descrive le dimensioni di un pollice di 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. Se si aumenta l'impostazione DPI il pollice di schermo diventa più grande; se si diminuisce, il pollice di schermo diventa più piccolo. Ciò significa che, nella maggior parte dei sistemi, un pollice di schermo non ha le stesse dimensioni di un pollice reale. Quando si aumenta il valore DPI, il testo e la grafica compatibili con DPI diventano più grandi poiché viene aumentata la dimensione del pollice di schermo. L'aumento del valore DPI può rendere il testo più leggibile, soprattutto a risoluzioni elevate.

Non tutte le applicazioni sono compatibili con il valore DPI: alcune usano i pixel hardware come unità di misura primaria. La modifica del valore DPI di sistema non ha alcun effetto su tali applicazioni. Molte altre applicazioni usano unità compatibili con DPI per descrivere le dimensioni dei tipi di carattere, ma usano i pixel per descrivere tutto il resto. L'eccessiva riduzione o l'eccessivo aumento del valore DPI può causare problemi di layout per queste applicazioni, poiché il testo delle applicazioni viene ridimensionato con l'impostazione DPI del sistema, ma non l'interfaccia utente. 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.

Graphics and text at different DPI settings
Grafica e testo con 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.

Hit Testing

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 l'hit testing per stabilire se un clic del mouse all'interno del rettangolo delimitatore di un oggetto rientra nella geometria di un cerchio. È anche possibile scegliere di eseguire l'override dell'implementazione predefinita dell'hit testing per eseguire calcoli di hit testing personalizzati.

Per altre informazioni sull'hit testing, vedere Hit testing a livello visivo.

Enumerazione della struttura ad albero visuale

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

L'esempio seguente illustra come enumerare tutti i discendenti di un oggetto visivo. Si tratta di una tecnica da usare se si desidera 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. Sebbene l'albero logico non venga modificato direttamente, la 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 Strutture ad albero 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 delimitatore di un oggetto visivo e di 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)

Vedi anche