wpfui 启动配置到优雅退出?WPF UI 生命周期各归谁管
【免费下载链接】wpfuiWPF UI provides the Fluent experience in your known and loved WPF framework. Intuitive design, themes, navigation and new immersive controls. All natively and effortlessly.项目地址: https://gitcode.com/GitHub_Trending/wp/wpfui
关主窗口时任务栏图标残留一会儿才消失,启动时主窗口晚半拍才出现,原因几乎都是同一个:窗口、服务、宿主在抢 WPF UI 生命周期里的职责。下面用示例工程逐项核对 wpfui 启动配置的归属。
窗口创建之前:WPF 依赖注入注册如何喂给主窗口
OnStartup之前,容器已经建好:
private static readonly IHost _host = Host.CreateDefaultBuilder() .ConfigureServices((context, services) => { _ = services.AddHostedService<ApplicationHostService>(); _ = services.AddSingleton<IThemeService, ThemeService>(); _ = services.AddSingleton<ITaskBarService, TaskBarService>(); _ = services.AddSingleton<INavigationService, NavigationService>(); _ = services.AddSingleton<INavigationWindow, Views.MainWindow>(); }) .Build();每一行都是“接口 → 实现”的映射:导航、主题、任务栏都挂在接口后面,主窗口自己也以INavigationWindow身份进了容器(见 App.xaml.cs)。容器实例化 MainWindow 时,视图模型和导航服务会直接交给它的构造函数,窗口自己不用new任何东西。
真正“造窗口”的是 ApplicationHostService。它是IHostedService,宿主调用StartAsync时接管窗口:
_navigationWindow = (serviceProvider.GetService(typeof(INavigationWindow)) as INavigationWindow)!; _navigationWindow!.ShowWindow(); _ = _navigationWindow.Navigate(typeof(Views.Pages.DashboardPage));三行干三件事:从容器取出主窗口、显示它、落到位仪表盘页。宿主不关心窗口长什么样,窗口也不关心自己从哪来。
窗口活着时:导航、主题、任务栏进度条各归一个服务
窗口存续期间有三条动态线,各自有独立服务负责,窗口只干一件事:接线。
先是导航。MainWindow.xaml.cs 在构造时把窗口里的INavigationView交给导航服务:
public MainWindow(ViewModels.MainWindowViewModel viewModel, INavigationService navigationService) { ViewModel = viewModel; DataContext = this; Appearance.SystemThemeWatcher.Watch(this); InitializeComponent(); navigationService.SetNavigationControl(RootNavigation); }SetNavigationControl把导航控件写进NavigationService,之后在视图模型里调Navigate(typeof(SettingsPage))就能换页,不用碰控件本身;Watch则让窗口跟随系统深浅色切换。
任务栏进度条 WPF:TaskBarService 按窗口存状态
有长耗时任务时,更新任务栏图标上的进度条:
taskBarService.SetValue(mainWindow, TaskBarProgressState.Normal, 50, 100);TaskBarService.cs 内部按窗口句柄维护一份Dictionary<IntPtr, TaskBarProgressState>,每个窗口的进度状态各存各的,多窗口互不干扰,支持Normal、Error、Paused等状态。
主题这条线则交给themeService.SetTheme(ApplicationTheme.Dark),由 ThemeService.cs 转发给ApplicationThemeManager.Apply,配合AppConfig即可把用户选择持久化。
WPF 优雅退出:停、放、存三步的顺序
退出表面是“窗口关了”,实际是一条链:窗口事件、应用关闭、宿主停止、容器释放,顺序不能乱。
MainWindow的OnClosed先调Application.Current.Shutdown(),把关窗升格为退应用;App.xaml 的Exit事件接着触发OnExit:
private async void OnExit(object sender, ExitEventArgs e) { await _host.StopAsync(); _host.Dispose(); }StopAsync会依次执行各托管服务的StopAsync,持久化逻辑(比如把主题选择写进 JSON)就该放在这里;随后Dispose释放容器。顺序反了,服务停止时会访问已释放的 provider。
📋 防翻车自查清单:启动卡、泄漏、崩溃未捕获
以下四项是 wpfui 项目翻车的高发点,发布前逐条过一遍:
- 启动卡:窗口构造函数里做同步读文件或长耗时网络调用。把耗时操作挪出构造函数,
StartAsync里用Task.Run跑慢操作。 - 内存泄漏:窗口订阅了静态事件或
SystemThemeWatcher却没取消,确认每处Watch都有对应清理。 - 崩溃未捕获:示例里的
OnDispatcherUnhandledException是空实现,至少写日志并置e.Handled = true再弹提示。 - 任务栏残留:退出前没
SetState(window, TaskBarProgressState.None),图标上的进度条状态会一直在。
一句话收束:容器喂窗口、服务跑窗口、宿主收窗口。现在就能做三件事:通读 App.xaml.cs 记住注册顺序;跑一遍 samples/Wpf.Ui.Demo.Mvvm/ 示例工程;对照 src/Wpf.Ui/ 下的服务文件核对本文职责归属。
【免费下载链接】wpfuiWPF UI provides the Fluent experience in your known and loved WPF framework. Intuitive design, themes, navigation and new immersive controls. All natively and effortlessly.项目地址: https://gitcode.com/GitHub_Trending/wp/wpfui
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考