WinUI3中从C#事件处理器操作UI的正确方法及页面切换方案
WinUI 3 页面切换与UI线程问题解决方案
1. 从UI线程正确捕获事件
OnAppIsReady事件确实可能在后台线程触发,而WinUI要求所有UI操作必须在UI线程执行。解决方法是通过DispatcherQueue将UI操作调度到UI线程:
实现代码
// MainWindow.xaml.cs public MainWindow() { this.InitializeComponent(); // 订阅App的初始化完成事件 App.OnAppIsReady += App_OnAppIsReady; // 初始化时先显示LoadingPage MainFrame.Navigate(typeof(LoadingPage)); } private void App_OnAppIsReady(object sender, EventArgs e) { // 强制在UI线程执行页面切换操作 DispatcherQueue.TryEnqueue(() => { MainFrame.Navigate(typeof(RegularContentPage)); // 清除导航栈,避免用户返回LoadingPage MainFrame.BackStack.Clear(); }); }
如果需要在App.xaml.cs中直接触发切换,也可以获取主窗口的DispatcherQueue来调度:
// App.xaml.cs private async void RunInitialization() { // 执行耗时初始化操作 await LoadAppResourcesAsync(); // 获取主窗口并调度UI操作 if (Application.Current.Windows[0] is MainWindow mainWindow) { mainWindow.DispatcherQueue.TryEnqueue(() => { mainWindow.MainFrame.Navigate(typeof(RegularContentPage)); mainWindow.MainFrame.BackStack.Clear(); }); } }
2. 更优的页面切换方案
推荐两种更贴合WinUI设计的方案:
方案一:基于Frame的原生导航管理
用MainWindow中的Frame作为页面容器,统一管理页面切换逻辑:
- 优点:遵循WinUI原生导航规范,自带导航栈管理,适合多页面场景
- 核心逻辑:初始化时导航到
LoadingPage,初始化完成后导航到RegularContentPage,同时清理导航栈避免返回加载页
方案二:MVVM模式下的数据绑定切换
通过ViewModel驱动视图切换,解耦UI与业务逻辑:
// MainViewModel.cs public class MainViewModel : INotifyPropertyChanged { private Page _currentPage; public Page CurrentPage { get => _currentPage; set { _currentPage = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } // MainWindow.xaml.cs public MainWindow() { this.InitializeComponent(); ViewModel = new MainViewModel(); // 初始显示LoadingPage ViewModel.CurrentPage = new LoadingPage(); DataContext = ViewModel; App.OnAppIsReady += App_OnAppIsReady; } public MainViewModel ViewModel { get; } private void App_OnAppIsReady(object sender, EventArgs e) { DispatcherQueue.TryEnqueue(() => { ViewModel.CurrentPage = new RegularContentPage(); }); } // MainWindow.xaml <ContentControl Content="{Binding CurrentPage}" />
- 优点:完全遵循MVVM模式,UI与业务逻辑分离,适合复杂应用的视图扩展
内容的提问来源于stack exchange,提问作者holycreeper
相关产品推荐
相关产品推荐

