WPF中所有窗口的基类型都是System.Windows.Window。Window通常用于SDI(SingleDocumentInterface)、MDI(MultipleDocumentInterface)窗口和对话框。Window在应用程序中除了一个设计用于托管顶级内容的控件外,就别无他物了。典型的,可以混合使用标记和代码来定义一个窗口。代码如下(这里使用VisualStudio 输出窗口查看调试信息):
xaml代码:
<Window x:Class="WindowDemo.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WindowDemo" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"> <Grid> <Button Content="测试" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Name="BtnOpenWindow" Click="BtnOpenWindow_Click"/> </Grid> </Window>
c#代码:
using System; using System.Windows; namespace WindowDemo { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); this.Unloaded += MainWindow_Unloaded; this.Initialized += MainWindow_Initialized; this.ContentRendered += MainWindow_ContentRendered; this.Loaded += MainWindow_Loaded; this.Activated += MainWindow_Activated; this.Deactivated += MainWindow_Deactivated; this.Closing += MainWindow_Closing; this.Closed += MainWindow_Closed; Console.WriteLine($"{this.Name}:Constructor"); } private void MainWindow_Closed(object sender, EventArgs e) { Console.WriteLine($"{this.Name}:Closed"); } private void MainWindow_Unloaded(object sender, RoutedEventArgs e) { Console.WriteLine($"{this.Name}:Unloaded"); } private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e) { Console.WriteLine($"{this.Name}:Closing"); } private void MainWindow_ContentRendered(object sender, EventArgs e) { Console.WriteLine($"{this.Name}:ContentRendered"); } private void MainWindow_Loaded(object sender, RoutedEventArgs e) { Console.WriteLine($"{this.Name}:Loaded"); } private void MainWindow_Deactivated(object sender, EventArgs e) { Console.WriteLine($"{this.Name}:Deactivated"); } private void MainWindow_Activated(object sender, EventArgs e) { Console.WriteLine($"{this.Name}:Activated"); } private void MainWindow_Initialized(object sender, EventArgs e) { Console.WriteLine($"{this.Name}:Initialized"); } private static int i = 0; private void BtnOpenWindow_Click(object sender, RoutedEventArgs e) { new MainWindow() { Name = $"window_{i}" }.Show(); i++; } } }
界面:
生命周期中事件执行顺序:
1.Constructor:构造函数创建窗体对象是调用,整个生命周期中调用一次
2.Activated:在窗口成为前台窗口时发生
3.Loaded:当对元素进行布局、呈现,且可将其用于交互时发生
4.ContentRendered:在呈现窗口的内容之后发生
5.用户与窗体进行交互
6.Closing:之后立即发生 Close 被调用,并且可以处理以取消关闭窗口
7.Deactivated:在窗口成为后台窗口时发生
8.Closed:当窗口即将关闭时发生
9.Unloaded:当元素从加载元素的元素树中移除时发生。
过程1:在创建窗体对象是调用,过程2-4:在调用Show、ShowDialog时触发,过程6-9:关闭窗口时触发(点击关闭按钮,而非Application.Current.Shutdown退出应用)
用户在运行系统上的多个窗口中切换时,Activated和Deactivated在窗口的生命周期里会发生多次。ContentRendered事件只对窗口第一次完全呈现出来进行触发。为了让一些事情能在所有内容都显示给用户之前马上执行,可以用Loaded事件;为了让一些事情能在所有内容都显示给用户之后马上执行,可以用ContentRendered事件。
PS:
1.Unloaded:应用程序开始关闭后(Application.Current.Shutdown();),不会引发此事件。 如果您将处理程序中的清理代码放 Unloaded 事件,例如对于 Window 或 UserControl, ,可能不会按预期方式调用它。
2. 根据 ShutdownMode 属性配置的不同,关闭窗体时Shutdown的隐式调用可能会导致Unloaded不会按预期的方式被调用。