将 MainWindow 置于最前面,而不是总是在最前面,然后等待它关闭

Bring MainWindow to front, not always on top, and wait for it to close

我有一个 WPF 配置实用程序,在我的 WIX 安装程序中有一个 window 运行,也可以在安装后独立 运行。 SO 包含将 window 置于最前面的解决方案,但它们使它始终位于顶部或代码 returns 立即。

当应用程序启动时,我想将 window 放在最前面。留给它自己,它会在我的 MSI 对话框下弹出。我还想让用户将其他 windows 移到它上面(它不应该总是在上面),我想等待 window 在代码中关闭。也许我太挑剔了,因为 WPF 似乎不支持这个。

目前,我有这个:

MainWindow.Topmost = true;
MainWindow.Show();
MainWindow.Activate();
MainWindow.Topmost = false;
MainWindow.Focus();

很棒,只是 MainWindow.Show() returns 立即恢复执行。过去,我们使用

MainWindow.TopMost = true;
MainWindow.ShowDialog();

但是这个 window 总是在最前面并且阻碍所有其他 windows(不是最好的用户体验)。还有其他选择吗?请随时建议我也错误地设计了这个。谢谢!

而不是使用

MainWindow.ShowDialog();

您可以在使用之前的代码后覆盖 window 的 Closing 事件:

    MainWindow.Topmost = true;
    MainWindow.Show();
    MainWindow.Activate();
    MainWindow.Topmost = false;
    MainWindow.Focus();
}

/// <summary>
/// Raises the <see cref="E:System.Windows.Window.Closing"/> event.
/// </summary>
/// <param name="e">A <see cref="T:System.ComponentModel.CancelEventArgs"/> that contains the event data.</param>
protected override void OnClosing(CancelEventArgs e)
{
    base.OnClosing(e);
}

编辑:

在关闭事件中,您可以使用回调(来自调用者)在关闭后继续 window。

或者,您应该检查安装程序 window 定位,然后调用

MainWindow.ShowDialog();

从而防止 MainWindow 一直处于最顶部。 在 MainWindow 关闭之前,它将阻止调用程序的执行。

编辑 2: 使用 topmost 可能不是最好的主意,因为它会将您的对话框移到任何 window 的前面(即使是用户移到安装程序前面的对话框)。 也许你应该添加另一个自定义操作而不需要额外的 windows?

你能修改 MainWindow 代码吗?如果是这样,只需将其放在其代码隐藏中:

protected override void OnActivated(EventArgs e)
{
    base.OnActivated(e);

    this.Topmost = true;
    this.Topmost = false;
}

那么,无论你使用.Show()还是.ShowDialog(),每次Window激活时,它都会自己移动到最前面。

编辑:如果您t/won不能修改 MainWindow 代码,您可以对 Activated 事件做同样的订阅:

MainWindow.Activated += new EventHandler(window_Activated);
MainWindow.ShowDialog();  // or .Show()

...

void window_Activated(object sender, EventArgs e)
{
    var window = sender as MainWindow;

    window.Topmost = true;
    window.Topmost = false;
}