Události životnosti objektů (WPF .NET)
Během své životnosti procházejí všechny objekty ve spravovaném kódu Microsoft .NET fázemi vytváření, použitía zničení. Windows Presentation Foundation (WPF) poskytuje oznámení o těchto fázích, ke kterým dochází u objektu, tím, že vyvolává události životnosti. Pro elementy na úrovni rámce WPF (vizuální objekty) WPF implementuje události životního cyklu Initialized, Loadeda Unloaded. Vývojáři mohou tyto události životního cyklu používat jako háky pro operace na pozadí, které zahrnují prvky. Tento článek popisuje události životnosti pro vizuální objekty a pak zavádí další události životnosti, které se konkrétně vztahují na prvky oken, hostitele navigace nebo objekty aplikace.
Požadavky
Tento článek předpokládá základní znalosti o tom, jak lze rozložení prvku WPF konceptualizovat jako strom, a že jste si přečetli přehled směrovaných událostí. Pokud chcete postupovat podle příkladů v tomto článku, pomůže vám to, pokud znáte jazyk XAML (Extensible Application Markup Language) a víte, jak psát aplikace WPF.
Události životního cyklu pro vizuální objekty
Prvky na úrovni architektury WPF jsou odvozeny od FrameworkElement nebo FrameworkContentElement. Události životnosti Initialized, Loadeda Unloaded jsou společné pro všechny prvky architektury WPF. Následující příklad ukazuje strom elementu, který je primárně implementován v XAML. XAML definuje nadřazený Canvas element, který obsahuje vnořené elementy, který každý používá syntaxi atributu XAML pro připojení Initialized
, Loaded
a Unloaded
obslužných rutin událostí životnosti.
<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>
Jedním z elementů XAML je vlastní ovládací prvek, který je odvozen od základní třídy, jež v souboru code-behind přiřazuje obslužné rutiny událostí životnosti.
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.
Výstup programu zobrazuje pořadí vyvolání Initialized
, Loaded
a Unloaded
událostí životnosti jednotlivých objektů stromu. Tyto události jsou popsány v následujících částech v pořadí, v jakém jsou vyvolány u každého objektu stromu.
Inicializovaná událost životnosti
Systém událostí WPF vyvolá událost Initialized u elementu:
- Když jsou nastaveny vlastnosti elementu.
- Přibližně ve stejnou dobu, kdy je objekt inicializován voláním jeho konstruktoru.
Některé vlastnosti elementu, například Panel.Children, mohou obsahovat podřízené prvky. Nadřazené prvky nemohou oznámit inicializaci, dokud nebudou inicializovány jejich podřízené prvky. Hodnoty vlastností se tedy nastavují od nejhlouběji vnořených elementů ve stromu elementů a následně postupující k nadřazeným prvkům až k kořenovému prvku aplikace. Vzhledem k tomu, že událost Initialized
nastane, když jsou vlastnosti prvku nastaveny, je tato událost nejprve vyvolána na nejhlouběji vnořený prvek definovaný v markupu, následně postupně na nadřazené prvky až po kořenovou část aplikace. Pokud se objekty dynamicky vytvářejí v code-behind, může být jejich inicializace nesprávně seřazená.
Systém událostí WPF nečeká na inicializaci všech prvků ve stromu elementů před vyvolání události Initialized
na elementu. Když tedy píšete obslužnou rutinu události Initialized
pro libovolný prvek, mějte na paměti, že okolní prvky v logickém nebo vizuálním stromu, zejména nadřazené prvky, možná nebyly vytvořeny. Nebo mohou být jejich členské proměnné a datové vazby neinicializované.
Poznámka
Když je událost Initialized
vyvolána na elementu, použití výrazů elementu, jako jsou dynamické prostředky nebo vazby, bude nevyhodnoceno.
Načtená událost životnosti
Systém událostí WPF vyvolá událost Loaded u elementu:
- Pokud je logický strom obsahující prvek dokončen a připojen ke zdroji prezentace. Zdroj prezentace poskytuje úchyt okna (HWND) a vykreslovací plochu.
- Když jsou datové vazby k místním zdrojům, například k jiným vlastnostem nebo přímo definovaným zdrojům dat, dokončeny.
- Jakmile systém rozložení vypočítá všechny potřebné hodnoty pro vykreslování.
- Před konečným vykreslením.
Událost Loaded
není vyvolána u žádného prvku ve stromu prvků, dokud nejsou všechny prvky v logickém stromu načteny. Systém událostí WPF nejprve vyvolá událost Loaded
na kořenovém prvku stromu elementu, poté na každém po sobě jdoucím podřízeném prvku směrem dolů až k nejhlouběji vnořeným prvkům. I když se tato událost může podobat tunelování směrované události, událost Loaded
nepřenáší data událostí z jednoho prvku do druhého, takže označení události jako zpracovávané nemá žádný vliv.
Poznámka
Systém událostí WPF nemůže zaručit dokončení asynchronních datových vazeb před událostí Loaded
. Asynchronní datové vazby se připojují k externím nebo dynamickým zdrojům.
Událost vyložení životnosti
Systém událostí WPF vyvolá událost Unloaded u elementu:
- Při odstranění jejího zdroje prezentace nebo
- Při odebrání vizuálního rodiče
Systém událostí WPF nejprve vyvolá událost Unloaded
na kořenovém prvku stromu elementů, pak na každém následujícím podřízeném elementu až na nejhlouběji vnořené elementy. I když se tato událost může podobat tunelovaným směrovaným událostem, událost Unloaded
nešíří data událostí z elementu do elementu, takže označení události jako zpracovaná nemá žádný vliv.
Když je u elementu vyvolána událost Unloaded
, jeho nadřazený prvek nebo jakýkoli prvek výše v logickém či vizuálním stromu již může být neaktivní. Zrušení znamená, že datová spojení elementu, odkazy na prostředky a styly již nejsou nastavené na jejich standardní nebo poslední známou hodnotu během běhu programu.
Jiné životní události
Z hlediska událostí životnosti existují čtyři hlavní typy objektů WPF: prvky obecně, prvky okna, hostitele navigace a objekty aplikace. Události životnosti Initialized, Loadeda Unloaded platí pro všechny prvky na úrovni architektury. Jiné události životnosti se konkrétně vztahují na prvky okna, hostitele navigace nebo objekty aplikace. Informace o těchto dalších událostech životnosti najdete tady:
- přehled správy aplikací pro objekty Application.
- Přehled windows WPF pro prvky Window.
- přehled navigace pro prvky Page, NavigationWindowa Frame.
Viz také
- Initialized
- Loaded
- Unloaded
- zpracování načtené události
- Načtená událost a inicializovaná událost
- stromy v WPF
- přehled událostí Routed
.NET Desktop feedback