十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

手把手搞懂 WPF UI 应用宿主与依赖注入:从服务注册到优雅退出

手把手搞懂 WPF UI 应用宿主与依赖注入:从服务注册到优雅退出 手把手搞懂 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 应用生命周期里最容易卡住人的地方。WPF UI 的示例项目用.NET Generic Host管理全部启动流程覆盖依赖注入Dependency Injection, DI注册、页面导航、主题与任务栏进度、退出时停止服务。读完你可以把自定义页面和服务注册进容器并定位窗口不显示、主题不跟随这类问题。 机制拆解WPF UI 的依赖注入容器怎么构建依赖注入容器怎么构建所有服务在一个地方注册WPF 本身没有服务容器示例借用 .NET Generic Host 把配置、日志和依赖注入放在一处主窗口和 ViewModel 也就成了容器里普通得不能再普通的注册对象。关键注册在 samples/Wpf.Ui.Demo.Mvvm/App.xaml.cs// samples/Wpf.Ui.Demo.Mvvm/App.xaml.csConfigureServices 里注册应用的全部服务 .ConfigureServices((context, services) { _ services.AddNavigationViewPageProvider(); _ services.AddHostedServiceApplicationHostService(); _ services.AddSingletonIThemeService, ThemeService(); _ services.AddSingletonITaskBarService, TaskBarService(); _ services.AddSingletonINavigationService, NavigationService(); _ services.AddSingletonINavigationWindow, Views.MainWindow(); _ services.AddSingletonViews.Pages.SettingsPage(); _ services.ConfigureAppConfig(context.Configuration.GetSection(nameof(AppConfig))); })你要加新服务时改这里加一行AddSingleton就够了窗口或 ViewModel 通过构造函数注入拿到它别处不用动。主窗口为什么由托管服务创建而不是写在 App 里把建窗口的逻辑直接塞进OnStartup会把应用何时启动和窗口怎么建两件事搅在一起。示例把它挪进托管服务IHostedService启动变成标准的StartAsync流程退出时StopAsync也对称地有了位置// samples/Wpf.Ui.Demo.Mvvm/Services/ApplicationHostService.cs宿主就绪后从容器取窗口并显示 private async Task HandleActivationAsync() { if (!Application.Current.Windows.OfTypeMainWindow().Any()) { _navigationWindow (serviceProvider.GetService(typeof(INavigationWindow)) as INavigationWindow)!; _navigationWindow!.ShowWindow(); _ _navigationWindow.Navigate(typeof(Views.Pages.DashboardPage)); } }要换初始页面就改Navigate的类型参数要加启动前置逻辑比如登录检查写在HandleActivationAsync调用之前。导航服务和导航窗口为什么拆成两个接口INavigationService只管导航控件不依赖窗口ViewModel 想调导航就不必持有窗口引用INavigationWindow管窗口本身负责显示、关闭和导航。两者靠窗口构造函数里的navigationService.SetNavigationControl(RootNavigation)这一行接上见 samples/Wpf.Ui.Demo.Mvvm/Views/MainWindow.xaml.cs。你要从别处打开新页面时对照 src/Wpf.Ui/INavigationService.cs 的接口定义Navigate(Type)系列重载就是你的入口。 场景实战导航、主题切换、任务栏进度条怎么接导航到自己的页面页面怎么注册进导航新加一个设置页你希望它能被代码导航到。关键是先注册再导航导航服务靠 DI 容器解析页面实例// 在 samples/Wpf.Ui.Demo.Mvvm/App.xaml.cs 注册页面再在能拿到 INavigationService 处导航 services.AddSingletonViews.Pages.SettingsPage(); _navigationService.Navigate(typeof(Views.Pages.SettingsPage));跑起来后调用Navigate会立即把内容区切到你的新页面把入口同时加进导航栏的数据源里点菜单项效果一致。主题和强调色怎么切一行进深色导航跑通后被问得最多的问题是外观怎么换。用户要在设置页切浅色/深色还要强调色跟着系统走IThemeService一次覆盖// ThemeService 已在 samples/Wpf.Ui.Demo.Mvvm/App.xaml.cs 注册构造函数注入 IThemeService 后调用 themeService.SetTheme(ApplicationTheme.Dark); themeService.SetSystemAccent(); _ themeService.GetTheme();跑起来后窗口背景和控件配色整体立即切换SetSystemAccent让应用强调色改用当前 Windows 个性化颜色。想让窗口自动跟随 Windows 的明暗模式就在主窗口构造函数里加一行Appearance.SystemThemeWatcher.Watch(this);示例的 Views/MainWindow.xaml.cs 就是这么做的。任务栏进度条怎么接长操作有进度可看导出文件这类长操作用户不想专门切回来窗口看进度把进度条挂到任务栏图标上即可// TaskBarService 已在 samples/Wpf.Ui.Demo.Mvvm/App.xaml.cs 注册构造函数注入 ITaskBarService 后调用 taskBarService.SetValue(mainWindow, TaskBarProgressState.Normal, 50, 100); taskBarService.SetState(mainWindow, TaskBarProgressState.None);跑起来后任务栏里的应用图标下方出现进度条第一行把它刷到 50%操作结束用第二行把进度条清掉。️ 排错手册WPF UI 应用生命周期的高频问题症状应用启动后没有任何窗口。原因窗口只在托管服务的StartAsync里创建ApplicationHostService没注册、或窗口没注册成INavigationWindow时容器取到空引用建窗被跳过。 解法在 App.xaml.cs 的ConfigureServices里补上services.AddHostedServiceApplicationHostService();和services.AddSingletonINavigationWindow, Views.MainWindow();并确认你的窗口类实现了INavigationWindow且写好了ShowWindow()。症状导航后白屏或抛异常页面出不来。原因导航服务靠INavigationViewPageProvider从容器解析页面没注册的页面类型解析不到。 解法ConfigureServices里加services.AddSingleton你的页面类型();并确认services.AddNavigationViewPageProvider();那一行存在换成自己的窗口后仍不生效检查窗口构造函数是否执行了navigationService.SetNavigationControl(RootNavigation)见 Views/MainWindow.xaml.cs 第 27 行。症状主题不跟随 Windows 明暗模式。原因跟随系统靠SystemThemeWatcher订阅窗口没调用时窗口永远停在初始主题。 解法主窗口构造函数里加Appearance.SystemThemeWatcher.Watch(this);示例的 Views/MainWindow.xaml.cs 第 23 行就有这一行。症状窗口点叉关闭了进程却不结束。原因WPF 只在所有窗口关闭后才结束进程示例用OnClosed主动触发收尾App.OnExit再停托管服务。 解法你的主窗口覆写OnClosed并调用Application.Current.Shutdown()同时确认 App.xaml.cs 的OnExit里有await _host.StopAsync();和_host.Dispose();两行第 90-95 行。症状SetTheme返回false以为没生效。原因这不是 bugThemeService.SetTheme会先比较当前主题没变化时直接返回false见 src/Wpf.Ui/ThemeService.cs 第 45-48 行。 解法设置前先用GetTheme()看当前值或处理掉false返回值。 扩展指引跑通示例后还能往哪看samples/Wpf.Ui.Demo.Mvvm/ — 完整宿主加 DI 示例适合想看全流程的人src/Wpf.Ui/ — 核心库源码适合想抠服务实现细节的人src/Wpf.Ui.DependencyInjection/ — 页面提供器 DI 扩展适合想换页面来源的人docs/documentation/getting-started.md — 入门文档适合第一次搭项目的人docs/migration/v4-migration.md — V4 迁移指南适合升级旧版本的人行动清单克隆仓库跑一遍示例git clone https://gitcode.com/GitHub_Trending/wp/wpfui然后打开运行samples/Wpf.Ui.Demo.Mvvm。在你自己的项目里照场景一的写法注册一个页面调用Navigate验证页面能切出来。在OnExit里加日志观察托管服务停止顺序确认退出流程干净。收个尾机制拆解回答了服务容器为什么这样搭场景实战给你三组能直接照抄的操作排错手册收了你最可能撞上的五个症状扩展指引标了下一步该看哪些文件。下一篇讲 WPF UI 的导航控件NavigationView把菜单项、页签和返回栈的内部实现拆开看。【免费下载链接】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),仅供参考
返回列表