Condividi tramite


Eventi del ciclo di vita degli oggetti (WPF .NET)

Durante il loro ciclo di vita, tutti gli oggetti nel codice gestito di Microsoft .NET attraversano le fasi di creazione, usoe distruzione. Windows Presentation Foundation (WPF) fornisce una notifica di queste fasi, man mano che si verificano in un oggetto, generando eventi del ciclo di vita. Per gli elementi a livello di framework WPF (oggetti visivi), WPF implementa gli eventi del ciclo di vita Initialized, Loadede Unloaded. Gli sviluppatori possono usare questi eventi del ciclo di vita come ganci per le operazioni code-behind che coinvolgono elementi. Questo articolo descrive gli eventi di ciclo di vita per gli oggetti visivi e quindi introduce altri eventi di ciclo di vita che si applicano in modo specifico agli elementi della finestra, agli host di navigazione o agli oggetti applicativi.

Prerequisiti

Questo articolo presuppone una conoscenza di base del modo in cui il layout degli elementi WPF viene concettualizzato come un albero e che avete letto la panoramica sugli eventi indirizzati. Per seguire gli esempi in questo articolo, è utile se si ha familiarità con Extensible Application Markup Language (XAML) e si sa come scrivere applicazioni WPF.

Eventi di ciclo di vita per oggetti visivi

Gli elementi a livello di framework WPF derivano da FrameworkElement o FrameworkContentElement. Gli eventi di durata Initialized, Loadede Unloaded sono comuni a tutti gli elementi a livello di framework WPF. L'esempio seguente mostra un albero degli elementi implementato principalmente in XAML. XAML definisce un elemento padre Canvas che contiene elementi annidati, che utilizzano la sintassi dell'attributo XAML per allegare Initialized, Loadede Unloaded gestori degli eventi di vita.

<Canvas x:Name="canvas">
    <StackPanel x:Name="outerStackPanel" Initialized="InitHandler" Loaded="LoadHandler" Unloaded="UnloadHandler">
        <custom:ComponentWrapper x:Name="componentWrapper" Initialized="InitHandler" Loaded="LoadHandler" Unloaded="UnloadHandler">
            <TextBox Name="textBox1" Initialized="InitHandler" Loaded="LoadHandler" Unloaded="UnloadHandler" />
            <TextBox Name="textBox2" Initialized="InitHandler" Loaded="LoadHandler" Unloaded="UnloadHandler" />
        </custom:ComponentWrapper>
    </StackPanel>
    <Button Content="Remove canvas child elements" Click="Button_Click"/>
</Canvas>

Uno degli elementi XAML è un controllo personalizzato, che deriva da una classe di base che assegna gestori di eventi con durata definita nel codice sottostante.

public partial class MainWindow : Window
{
    public MainWindow() => InitializeComponent();

    // Handler for the Initialized lifetime event (attached in XAML).
    private void InitHandler(object sender, System.EventArgs e) => 
        Debug.WriteLine($"Initialized event on {((FrameworkElement)sender).Name}.");

    // Handler for the Loaded lifetime event (attached in XAML).
    private void LoadHandler(object sender, RoutedEventArgs e) => 
        Debug.WriteLine($"Loaded event on {((FrameworkElement)sender).Name}.");

    // Handler for the Unloaded lifetime event (attached in XAML).
    private void UnloadHandler(object sender, RoutedEventArgs e) =>
        Debug.WriteLine($"Unloaded event on {((FrameworkElement)sender).Name}.");

    // Remove nested controls.
    private void Button_Click(object sender, RoutedEventArgs e) => 
        canvas.Children.Clear();
}

// Custom control.
public class ComponentWrapper : ComponentWrapperBase { }

// Custom base control.
public class ComponentWrapperBase : StackPanel
{
    public ComponentWrapperBase()
    {
        // Assign handler for the Initialized lifetime event (attached in code-behind).
        Initialized += (object sender, System.EventArgs e) => 
            Debug.WriteLine($"Initialized event on componentWrapperBase.");

        // Assign handler for the Loaded lifetime event (attached in code-behind).
        Loaded += (object sender, RoutedEventArgs e) => 
            Debug.WriteLine($"Loaded event on componentWrapperBase.");

        // Assign handler for the Unloaded lifetime event (attached in code-behind).
        Unloaded += (object sender, RoutedEventArgs e) => 
            Debug.WriteLine($"Unloaded event on componentWrapperBase.");
    }
}

/* Output:
Initialized event on textBox1.
Initialized event on textBox2.
Initialized event on componentWrapperBase.
Initialized event on componentWrapper.
Initialized event on outerStackPanel.

Loaded event on outerStackPanel.
Loaded event on componentWrapperBase.
Loaded event on componentWrapper.
Loaded event on textBox1.
Loaded event on textBox2.

Unloaded event on outerStackPanel.
Unloaded event on componentWrapperBase.
Unloaded event on componentWrapper.
Unloaded event on textBox1.
Unloaded event on textBox2.
*/
Partial Public Class MainWindow
    Inherits Window

    Public Sub New()
        InitializeComponent()
    End Sub

    ' Handler for the Initialized lifetime event (attached in XAML).
    Private Sub InitHandler(sender As Object, e As EventArgs)
        Debug.WriteLine($"Initialized event on {CType(sender, FrameworkElement).Name}.")
    End Sub

    ' Handler for the Loaded lifetime event (attached in XAML).
    Private Sub LoadHandler(sender As Object, e As RoutedEventArgs)
        Debug.WriteLine($"Loaded event on {CType(sender, FrameworkElement).Name}.")
    End Sub

    ' Handler for the Unloaded lifetime event (attached in XAML).
    Private Sub UnloadHandler(sender As Object, e As RoutedEventArgs)
        Debug.WriteLine($"Unloaded event on {CType(sender, FrameworkElement).Name}.")
    End Sub

    Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
        ' Remove nested controls.
        canvas.Children.Clear()
    End Sub
End Class

' Custom control.
Public Class ComponentWrapper
    Inherits ComponentWrapperBase
End Class

' Custom base control.
Public Class ComponentWrapperBase
    Inherits StackPanel

    Public Sub New()
        ' Attach handlers for the lifetime events.
        AddHandler Initialized, AddressOf InitHandler
        AddHandler Loaded, AddressOf LoadHandler
        AddHandler Unloaded, AddressOf UnloadHandler
    End Sub

    ' Handler for the Initialized lifetime event (attached in code-behind).
    Private Sub InitHandler(sender As Object, e As EventArgs)
        Debug.WriteLine("Initialized event on componentWrapperBase.")
    End Sub

    ' Handler for the Loaded lifetime event (attached in code-behind).
    Private Sub LoadHandler(sender As Object, e As RoutedEventArgs)
        Debug.WriteLine("Loaded event on componentWrapperBase.")
    End Sub

    ' Handler for the Unloaded lifetime event (attached in code-behind).
    Private Sub UnloadHandler(sender As Object, e As RoutedEventArgs)
        Debug.WriteLine("Unloaded event on componentWrapperBase.")
    End Sub
End Class

'Output:
'Initialized event on textBox1.
'Initialized event on textBox2.
'Initialized event on componentWrapperBase.
'Initialized event on componentWrapper.
'Initialized event on outerStackPanel.

'Loaded event on outerStackPanel.
'Loaded event on componentWrapperBase.
'Loaded event on componentWrapper.
'Loaded event on textBox1.
'Loaded event on textBox2.

'Unloaded event on outerStackPanel.
'Unloaded event on componentWrapperBase.
'Unloaded event on componentWrapper.
'Unloaded event on textBox1.
'Unloaded event on textBox2.

L'output del programma mostra l'ordine di chiamata degli eventi del ciclo di vita di Initialized, Loadede Unloaded su ciascun oggetto albero. Tali eventi sono descritti nelle sezioni seguenti, nell'ordine in cui vengono generati in ogni oggetto dell'albero.

Evento del ciclo di vita inizializzato

Il sistema di eventi WPF attiva l'evento Initialized su un determinato elemento.

  • Quando vengono impostate le proprietà dell'elemento.
  • Nello stesso momento in cui l'oggetto viene inizializzato tramite una chiamata al relativo costruttore.

Alcune proprietà degli elementi, come Panel.Children, possono contenere sottoelementi. Gli elementi padre non possono segnalare l'inizializzazione finché i relativi elementi figlio non vengono inizializzati. I valori delle proprietà vengono quindi impostati a partire dagli elementi annidati più in profondità in un albero degli elementi, seguiti da elementi padre successivi fino alla radice dell'applicazione. Poiché l'evento Initialized si verifica quando vengono impostate le proprietà di un elemento, tale evento viene innanzitutto richiamato sugli elementi annidati più profondamente definiti nel markup, seguiti da elementi padre successivi fino alla radice dell'applicazione. Quando gli oggetti vengono creati dinamicamente nel code-behind, l'inizializzazione potrebbe non avvenire nell'ordine corretto.

Il sistema di eventi WPF non attende che tutti gli elementi di un albero degli elementi vengano inizializzati prima di generare l'evento Initialized su un elemento. Di conseguenza, quando si scrive un gestore eventi Initialized per qualsiasi elemento, è importante tenere presente che gli elementi circostanti nella struttura ad albero logica o visiva, in particolare gli elementi padre, potrebbero non essere stati ancora creati. In alternativa, le variabili membro e i collegamenti dati potrebbero non essere inizializzati.

Nota

Quando l'evento Initialized viene generato su un elemento, l'utilizzo delle espressioni dell'elemento, ad esempio risorse dinamiche o binding, non verrà valutato.

Evento di ciclo di vita caricato

Il sistema di eventi WPF genera l'evento Loaded su un elemento:

  • Quando l'albero logico che contiene l'elemento è completo e connesso a un'origine di presentazione. La sorgente della presentazione fornisce l'handle della finestra (HWND) e la superficie di rendering.
  • Quando il data binding alle origini locali, ad esempio altre proprietà o origini dati definite direttamente, è completo.
  • Dopo che il sistema di layout ha calcolato tutti i valori necessari per il rendering.
  • Prima del rendering finale.

L'evento Loaded non viene generato in alcun elemento di un albero degli elementi fino a quando non vengono caricati tutti gli elementi all'interno dell'albero logico . Il sistema di eventi WPF genera prima l'evento Loaded sull'elemento radice di un albero degli elementi, quindi su ogni elemento figlio successivo fino agli elementi più profondamente annidati. Anche se questo evento potrebbe essere simile a un tunneling evento indirizzato, l'evento Loaded non trasporta i dati dell'evento da un elemento a un altro, quindi contrassegnare l'evento come gestito non ha alcun effetto.

Nota

Il sistema di eventi WPF non può garantire che i data binding asincroni siano stati completati prima dell'evento Loaded. Le associazioni di dati asincrone si collegano a origini esterne o dinamiche.

Evento di durata scaricata

Il sistema di eventi WPF genera l'evento Unloaded su un elemento:

  • In caso di rimozione della sua fonte di presentazione o
  • Al termine della rimozione dell'elemento padre visivo.

Il sistema di eventi WPF genera prima l'evento Unloaded sull'elemento radice di un albero degli elementi, quindi su ogni elemento figlio successivo fino agli elementi più profondamente annidati. Anche se questo evento potrebbe essere simile a un tunneling evento indirizzato, l'evento Unloaded non propaga i dati dell'evento dall'elemento all'elemento, quindi contrassegnare l'evento come gestito non ha alcun effetto.

Quando l'evento Unloaded viene generato su un elemento, è elemento padre o qualsiasi elemento superiore nella struttura ad albero logica o visiva potrebbe essere già stato unset. Unset indica che i data binding, i riferimenti alle risorse e gli stili di un elemento non sono più impostati al loro valore normale o all'ultimo valore noto in fase di esecuzione.

Altri eventi della vita

Dal punto di vista degli eventi del ciclo di vita, esistono quattro tipi principali di oggetti WPF: elementi in generale, elementi della finestra, host di navigazione e oggetti applicazione. Gli eventi di ciclo di vita Initialized, Loadede Unloaded si applicano a tutti gli elementi a livello di framework. Altri eventi del ciclo di vita si applicano in modo specifico agli elementi della finestra, agli host di navigazione o agli oggetti dell'applicazione. Per informazioni sugli altri eventi significativi della vita, vedere:

Vedere anche