Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Während ihrer Lebensdauer durchlaufen alle Objekte in verwaltetem Microsoft .NET-Code Erstellungs-, Verwendungs- und Zerstörungsphasen . Windows Presentation Foundation (WPF) stellt Benachrichtigungen über diese Phasen bereit, wenn sie in einem Objekt auftreten, indem Lebensdauerereignisse ausgelöst werden. Für WPF-Frameworkebenenelemente (visuelle Objekte) implementiert WPF die InitializedEreignisse , Loadedund Unloaded Lebensdauer. Entwickler können diese Lebenszeitereignisse als Hooks für CodeBehind-Vorgänge verwenden, die Elemente einbeziehen. In diesem Artikel werden die Lebensdauerereignisse für visuelle Objekte beschrieben, und anschließend werden andere Lebenszeitereignisse vorgestellt, die speziell auf Fensterelemente, Navigationshosts oder Anwendungsobjekte angewendet werden.
Voraussetzungen
In diesem Artikel wird davon ausgegangen, dass Sie grundlegende Kenntnisse darüber haben, wie das WPF-Elementlayout als Struktur konzipiert werden kann und dass Sie die Übersicht über Routingereignisse gelesen haben. Um den Beispielen in diesem Artikel zu folgen, hilft es Ihnen, wenn Sie mit Extensible Application Markup Language (XAML) vertraut sind und wissen, wie WPF-Anwendungen geschrieben werden.
Lebensdauerereignisse für visuelle Objekte
WPF-Frameworkebenenelemente werden von oder FrameworkElementabgeleitetFrameworkContentElement. Die InitializedEreignisse " , Loaded" und Unloaded "Lifetime" gelten für alle WPF-Frameworkebenenelemente. Das folgende Beispiel zeigt eine Elementstruktur, die in erster Linie in XAML implementiert ist. Der XAML-Code definiert ein übergeordnetes Canvas Element, das geschachtelte Elemente enthält, die jeweils die XAML-Attributsyntax zum Anfügen Initializedvon Ereignishandlern und LoadedUnloaded Lebenszeit-Ereignishandlern verwenden.
<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>
Eines der XAML-Elemente ist ein benutzerdefiniertes Steuerelement, das von einer Basisklasse abgeleitet wird, die Lebenszyklus-Ereignishandler im Code-Behind zuweist.
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.
Die Programmausgabe zeigt die Reihenfolge des Aufrufs von Initialized, Loaded und Unloaded Lebenszyklusereignissen für jedes Baumobjekt. Diese Ereignisse werden in den folgenden Abschnitten in der Reihenfolge beschrieben, in der sie für jedes Baumobjekt ausgelöst werden.
Initialisiertes Lebenszyklusereignis
Das WPF-Ereignissystem löst das Initialized Ereignis für ein Element aus:
- Wenn die Eigenschaften des Elements festgelegt werden.
- Ungefähr zur gleichen Zeit, wenn das Objekt durch einen Aufruf seines Konstruktors initialisiert wird.
Einige Elementeigenschaften, wie z.B. Panel.Children, können untergeordnete Elemente enthalten. Übergeordnete Elemente können die Initialisierung erst melden, wenn ihre untergeordneten Elemente initialisiert werden. Eigenschaftenwerte werden also beginnend mit den tief geschachtelten Elementen in einer Elementstruktur festgelegt, gefolgt von aufeinander folgenden übergeordneten Elementen bis zum Anwendungsstamm. Da das Ereignis auftritt, wenn die Initialized Eigenschaften eines Elements festgelegt werden, wird dieses Ereignis zuerst für die am tiefsten geschachtelten Elemente(n) aufgerufen, die im Markup definiert sind, gefolgt von den jeweils übergeordneten Elementen bis zum Anwendungsstamm. Wenn Objekte dynamisch in CodeBehind erstellt werden, ist die Initialisierung möglicherweise nicht mehr sequenziert.
Das WPF-Ereignissystem wartet nicht darauf, dass alle Elemente in einer Elementstruktur initialisiert werden, bevor das Initialized Ereignis für ein Element ausgelöst wird. Wenn Sie also einen Initialized Ereignishandler für jedes Element schreiben, denken Sie daran, dass umgebende Elemente in der logischen oder visuellen Struktur, insbesondere übergeordnete Elemente, möglicherweise nicht erstellt wurden. Oder ihre Membervariablen und Datenbindungen könnten nicht initialisiert sein.
Hinweis
Wenn das Initialized Ereignis für ein Element ausgelöst wird, werden die Ausdrucksverwendungen des Elements, z. B. dynamische Ressourcen oder Bindung, nicht ausgewertet.
Geladenes Lebenszeitereignis
Das WPF-Ereignissystem löst das Loaded Ereignis für ein Element aus:
- Wenn die logische Struktur, die das Element enthält, vollständig ist und mit einer Präsentationsquelle verbunden ist. Die Präsentationsquelle stellt das Fensterhandle (HWND) und die Renderingoberfläche bereit.
- Wenn die Datenbindung an lokale Quellen, z. B. andere Eigenschaften oder direkt definierte Datenquellen, abgeschlossen ist.
- Nachdem das Layoutsystem alle erforderlichen Werte für das Rendern berechnet hat.
- Vor dem endgültigen Rendering.
Das Loaded Ereignis wird für ein Element in einer Elementstruktur erst ausgelöst, wenn alle Elemente innerhalb der logischen Struktur geladen werden. Das WPF-Ereignissystem löst zuerst das Loaded Ereignis auf dem Stammelement eines Elementbaums aus, dann auf jedem nachfolgenden untergeordneten Element bis zu den tiefst geschachtelten Element(en). Dieses Ereignis kann zwar einem Tunneling-Ereignis ähneln, aber das Loaded Ereignis überträgt keine Ereignisdaten von einem Element auf ein anderes, sodass das Markieren des Ereignisses als behandelt keine Auswirkung hat.
Hinweis
Das WPF-Ereignissystem kann nicht garantieren, dass asynchrone Datenbindungen vor dem Loaded Ereignis abgeschlossen wurden. Asynchrone Datenbindungen binden an externe oder dynamische Quellen.
nicht geladenes Lebensdauerereignis
Das WPF-Ereignissystem löst das Unloaded Ereignis für ein Element aus:
- Beim Entfernen der Präsentationsquelle oder
- Bei Entfernung des visuellen Elternteils.
Das WPF-Ereignissystem löst zuerst das Unloaded Ereignis auf dem Stammelement eines Elementbaums aus, dann auf jedem nachfolgenden untergeordneten Element bis zu den tiefst geschachtelten Element(en). Obwohl dieses Ereignis einem Tunnelingroutenereignis ähnelt, gibt das Unloaded Ereignis keine Ereignisdaten von Element an Element weiter, sodass das Markieren des Ereignisses als behandelt keine Auswirkung hat.
Wenn das Unloaded Ereignis für ein Element ausgelöst wird, kann das übergeordnete Element oder ein beliebiges Element weiter oben in der logischen oder visuellen Struktur möglicherweise bereits zurückgesetzt sein. Unset bedeutet, dass die Datenbindungen, Ressourcenverweise und Stile eines Elements nicht mehr auf ihren normalen oder letzten bekannten Laufzeitwert festgelegt sind.
Andere Lebenszeitereignisse
Aus Sicht der Lebensdauerereignisse gibt es vier Haupttypen von WPF-Objekten: Elemente im Allgemeinen, Fensterelemente, Navigationshosts und Anwendungsobjekte. Die Lebensdauerereignisse Initialized, Loaded und Unloaded gelten für alle Elemente auf Frameworkebene. Andere Lebenszeitereignisse gelten speziell für Fensterelemente, Navigationshosts oder Anwendungsobjekte. Informationen zu diesen anderen Lebenszeitereignissen finden Sie unter:
- Übersicht über die Anwendungsverwaltung
- Übersicht über WPF-Fenster für Window Elemente.
- Navigationsübersicht
Siehe auch
.NET Desktop feedback