如果这个问题已被多次回答,我深表歉意,但我似乎找不到适合我的答案。我想创建一个模式窗口,在我的应用程序执行长时间运行的任务时显示各种进度消息。这些任务在单独的线程上运行,我能够在流程的不同阶段更新进度窗口上的文本。跨线程通信一切正常。问题是我无法让窗口仅位于其他应用程序窗口(不是计算机上的每个应用程序)之上,保持在顶部,阻止与父窗口交互,并且仍然允许工作继续。
这是我到目前为止所尝试的:
首先,我的启动窗口是一个自定义类,它扩展了 Window 类并具有更新消息框的方法。我很早就创建了一个新的启动类实例,并根据需要显示/隐藏它。
在最简单的情况下,我实例化窗口并调用.Show()
它:
//from inside my secondary thread
this._splash.Dispatcher.Invoke(new Action(() => this._splash.Show());
//Do things
//update splash text
//Do more things
//close the splash when done
this._splash.Dispatcher.Invoke(new Action(() => this._splash.Hide());
这会正确显示窗口并继续运行我的代码来处理初始化任务,但它允许我单击父窗口并将其带到前面。
接下来我尝试禁用主窗口并稍后重新启用:
Application.Current.Dispatcher.Invoke(new Action(() => this.MainWindow.IsEnabled = false));
//show splash, do things, etc
Application.Current.Dispatcher.Invoke(new Action(() => this.MainWindow.IsEnabled = true));
这会禁用窗口中的所有元素,但我仍然可以单击主窗口并将其带到启动屏幕的前面,这不是我想要的。
接下来,我尝试在启动窗口中使用 topmost 属性。这使它保持在所有事物的前面,并且结合设置主窗口的 IsEnabled 属性,我可以阻止交互,但这会使启动屏幕出现在所有事物的前面,包括其他应用程序。我也不想要那个。我只是希望它成为此应用程序中最顶层的窗口。
然后我发现了关于 using.ShowDialog()
而不是.Show()
. 我试过了,它正确地显示了对话框,并且不允许我单击父窗口,但是调用.ShowDialog()
会使程序挂起,等待您关闭对话框,然后才能继续运行代码。这显然不是我想要的。我想我可以调用ShowDialog()
一个不同的线程,以便该线程挂起,但执行工作的线程不会……这是推荐的方法吗?
我还考虑过根本不使用窗口的可能性,而是将一个全尺寸的窗口元素放在页面上其他所有内容的前面。除了我打开了其他窗口并且我希望能够在这些窗口也打开时使用启动画面之外,这将起作用。如果我使用一个窗口元素,我将不得不在每个窗口上重新创建它,并且我将无法UpdateSplashText
在我的自定义启动类中使用我方便的方法。
所以这让我想到了这个问题。处理这个问题的正确方法是什么?
感谢您的宝贵时间,很抱歉这个问题很长,但细节很重要:)