为什么不能在 Window 构造函数中显示两次 FolderBrowserDialog?
Why can't show FolderBrowserDialog twice in Window constructor?
出于好奇,我想知道为什么我不能在 Window
的构造函数中一个接一个地显示 FolderBrowserDialog
的两个不同实例,但可以在 [=14] =]的Loaded
事件。
- 示例 1 仅显示第一个对话框 (
fbd1
),不显示下一个。
- 示例 2 显示了两个对话框。
示例 1:
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
using (var fbd1 = new FolderBrowserDialog()) {
fbd1.ShowDialog();
}
using (var fbd2 = new FolderBrowserDialog()) {
fbd2.ShowDialog();
}
}
}
示例 2:
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e) {
using (var fbd1 = new FolderBrowserDialog()) {
fbd1.ShowDialog();
}
using (var fbd2 = new FolderBrowserDialog()) {
fbd2.ShowDialog();
}
}
}
顺便说一下,我也用 WinForms 测试过,这几乎是一样的。
它在 Form
的构造函数 和 中的 Form
的 Load
事件中不起作用,但在Shown
事件。
正如 Reza Aghaei 在他的第二条评论中所说:
When you close the first dialog, the second one appears, but since
your Form
is not visible at the moment and is not visible in task-bar,
it doesn't activate the second dialog, while it's open behind other
windows. Just press Alt+Tab to see open windows and you will see the
second dialog too. But when your Form is visible (for example when run
code in Shown) you will not have this issue.
这就是我好奇的答案。
您喜欢的答案实际上并不是正确答案,它实际上确实激活了第二个对话框。激活状态和 Z 顺序是不同的 windows 属性。你只是看不到对话框,因为你失去了前景。只有当你有一个可以留在前台的 window 时,你才能永远保留它。
一个程序在启动后有大约 6 秒的时间用自己的 window 窃取前台。超时很容易看到,Windows 显示 Cursors.AppStarting 光标(带沙漏的小箭头)。这有助于将第一个对话置于前台。然而,接下来发生的事情注定会出错。当用户关闭对话框时,您的应用程序没有 window 可以移动到前台。 Windows 现在正在寻找另一个 window 放在前台,不可避免地由另一个进程拥有。例如,当您调试时很可能是 VS main window。并且 6 秒已经过期。第二个对话框将出现并被激活,但当然它与 window.
重叠
一个冷酷的事实是,对话框必须总是 有一个所有者。 FolderBrowserDialog 对此有点过于宽容,它为您提供了没有所有者参数的 ShowDialog() 重载。非常方便,并不总是正确的。它在后台使用 GetActiveWindow() 来查找所有者。如果没有,则桌面 window 成为所有者,麻烦就在前面,
否则不会抛出异常。
出于好奇,我想知道为什么我不能在 Window
的构造函数中一个接一个地显示 FolderBrowserDialog
的两个不同实例,但可以在 [=14] =]的Loaded
事件。
- 示例 1 仅显示第一个对话框 (
fbd1
),不显示下一个。 - 示例 2 显示了两个对话框。
示例 1:
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
using (var fbd1 = new FolderBrowserDialog()) {
fbd1.ShowDialog();
}
using (var fbd2 = new FolderBrowserDialog()) {
fbd2.ShowDialog();
}
}
}
示例 2:
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e) {
using (var fbd1 = new FolderBrowserDialog()) {
fbd1.ShowDialog();
}
using (var fbd2 = new FolderBrowserDialog()) {
fbd2.ShowDialog();
}
}
}
顺便说一下,我也用 WinForms 测试过,这几乎是一样的。
它在 Form
的构造函数 和 中的 Form
的 Load
事件中不起作用,但在Shown
事件。
正如 Reza Aghaei 在他的第二条评论中所说:
When you close the first dialog, the second one appears, but since your
Form
is not visible at the moment and is not visible in task-bar, it doesn't activate the second dialog, while it's open behind other windows. Just press Alt+Tab to see open windows and you will see the second dialog too. But when your Form is visible (for example when run code in Shown) you will not have this issue.
这就是我好奇的答案。
您喜欢的答案实际上并不是正确答案,它实际上确实激活了第二个对话框。激活状态和 Z 顺序是不同的 windows 属性。你只是看不到对话框,因为你失去了前景。只有当你有一个可以留在前台的 window 时,你才能永远保留它。
一个程序在启动后有大约 6 秒的时间用自己的 window 窃取前台。超时很容易看到,Windows 显示 Cursors.AppStarting 光标(带沙漏的小箭头)。这有助于将第一个对话置于前台。然而,接下来发生的事情注定会出错。当用户关闭对话框时,您的应用程序没有 window 可以移动到前台。 Windows 现在正在寻找另一个 window 放在前台,不可避免地由另一个进程拥有。例如,当您调试时很可能是 VS main window。并且 6 秒已经过期。第二个对话框将出现并被激活,但当然它与 window.
重叠一个冷酷的事实是,对话框必须总是 有一个所有者。 FolderBrowserDialog 对此有点过于宽容,它为您提供了没有所有者参数的 ShowDialog() 重载。非常方便,并不总是正确的。它在后台使用 GetActiveWindow() 来查找所有者。如果没有,则桌面 window 成为所有者,麻烦就在前面, 否则不会抛出异常。