WPF 启动画面 UI 未更新
WPF splash screen UI not updating
我的 WPF 应用程序上有启动画面。 splash window 在我的 App
class 中定义为一个字段,在 Startup
事件中,我执行了可能需要一些时间的各种初始化功能,显示 prompts/windows,等等。我的启动事件看起来像这样:
Startup += (_,__) =>
{
mySplashScreen.UpdateMessage("Initializing Component A...");
InitializeComponentA();
mySplashScreen.UpdateMessage("Initializing Component B...");
InitializeComponentB();
mySplashScreen.UpdateMessage("Initializing Component C...");
InitializeComponentC();
mySplashScreen.UpdateMessage("Opening application...");
};
关于启动画面的更新方法,我试过以下方法:
- 使用实现
INotifyPropertyChanged
的 ViewModel class,绑定到它,并更新视图模型的 Message
属性.
- 在代码隐藏中创建一个名为
Message
的 DependencyProperty
,然后 binding/updating 那个。
- 直接设置属性(例如
myTextBlock.Text = splashMessage;
)
- 将初始屏幕放在单独的线程中并通过
Dispatcher.Invoke()
设置初始消息(使用 DispatcherPriority.Send
以确保 UI 立即更新)。
我的问题是 none 的初始屏幕消息是 updating/displaying 在 window 上。启动 UI 更新的 仅 条件是 InitializeComponentX()
方法之一显示对话框时。在这种情况下,启动 UI 会更新。对于上面的所有选项,我什至尝试过同步和异步等待(通过 Thread.Sleep()
)几秒钟,看看 UI 是否会更新,但它永远不会。
为什么我的启动画面 UI 只有在我显示另一个 dialog/window 时才会更新?
Why is my splash UI only updating if I show another dialog/window?
您完全阻塞了 UI 线程,这会阻止 WPF 处理和显示您的更新。
您需要将工作移至后台线程。
您可以使用异步和等待机制将组件的初始化推送到工作线程。像这样:
mySplashScreen.UpdateMessage("Initializing Component A...");
await InitializeComponentAAsync();
mySplashScreen.UpdateMessage("Initializing Component B...");
await InitializeComponentBAsync();
mySplashScreen.UpdateMessage("Initializing Component C...");
await InitializeComponentCAsync();
mySplashScreen.UpdateMessage("Opening application...");
它需要更改必须变为异步的 initialisecomponent 方法。但它不应该是一个非常大的更新。
我还更新了方法名称,使它们符合异步方法以 'Async' 结尾的约定。
这释放了 GUI 线程,应该会进行更新。
如果您还没有此版本的 .NET,您可以使用后台工作者和用户报告进度来初始化所有内容以更新初始屏幕。我觉得不难。
我的 WPF 应用程序上有启动画面。 splash window 在我的 App
class 中定义为一个字段,在 Startup
事件中,我执行了可能需要一些时间的各种初始化功能,显示 prompts/windows,等等。我的启动事件看起来像这样:
Startup += (_,__) =>
{
mySplashScreen.UpdateMessage("Initializing Component A...");
InitializeComponentA();
mySplashScreen.UpdateMessage("Initializing Component B...");
InitializeComponentB();
mySplashScreen.UpdateMessage("Initializing Component C...");
InitializeComponentC();
mySplashScreen.UpdateMessage("Opening application...");
};
关于启动画面的更新方法,我试过以下方法:
- 使用实现
INotifyPropertyChanged
的 ViewModel class,绑定到它,并更新视图模型的Message
属性. - 在代码隐藏中创建一个名为
Message
的DependencyProperty
,然后 binding/updating 那个。 - 直接设置属性(例如
myTextBlock.Text = splashMessage;
) - 将初始屏幕放在单独的线程中并通过
Dispatcher.Invoke()
设置初始消息(使用DispatcherPriority.Send
以确保 UI 立即更新)。
我的问题是 none 的初始屏幕消息是 updating/displaying 在 window 上。启动 UI 更新的 仅 条件是 InitializeComponentX()
方法之一显示对话框时。在这种情况下,启动 UI 会更新。对于上面的所有选项,我什至尝试过同步和异步等待(通过 Thread.Sleep()
)几秒钟,看看 UI 是否会更新,但它永远不会。
为什么我的启动画面 UI 只有在我显示另一个 dialog/window 时才会更新?
Why is my splash UI only updating if I show another dialog/window?
您完全阻塞了 UI 线程,这会阻止 WPF 处理和显示您的更新。
您需要将工作移至后台线程。
您可以使用异步和等待机制将组件的初始化推送到工作线程。像这样:
mySplashScreen.UpdateMessage("Initializing Component A...");
await InitializeComponentAAsync();
mySplashScreen.UpdateMessage("Initializing Component B...");
await InitializeComponentBAsync();
mySplashScreen.UpdateMessage("Initializing Component C...");
await InitializeComponentCAsync();
mySplashScreen.UpdateMessage("Opening application...");
它需要更改必须变为异步的 initialisecomponent 方法。但它不应该是一个非常大的更新。 我还更新了方法名称,使它们符合异步方法以 'Async' 结尾的约定。 这释放了 GUI 线程,应该会进行更新。
如果您还没有此版本的 .NET,您可以使用后台工作者和用户报告进度来初始化所有内容以更新初始屏幕。我觉得不难。