首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用ShowDialog()的WPF模式窗口会阻塞所有其他窗口

使用ShowDialog()的WPF模式窗口会阻塞所有其他窗口
EN

Stack Overflow用户
提问于 2010-04-07 23:00:04
回答 1查看 21.3K关注 0票数 24

我的应用程序有几个独立的“顶层”窗口,它们都有完全不同的功能/工作流程。

我目前正在使用ShowDialog()来创建一个WPF窗口模式。模式窗口是其中一个主窗口的子窗口。然而,一旦打开,它就会阻塞所有的顶级窗口。我希望对话框只阻止启动它的父窗口。这个是可能的吗?

我不确定这是否重要,但打开对话框的窗口是应用程序的初始窗口--所以所有其他顶级窗口都是从它打开的。

EN

回答 1

Stack Overflow用户

发布于 2014-04-09 21:34:31

我遇到了同样的问题,并实现了这篇文章中描述的模式对话框行为:http://social.msdn.microsoft.com/Forums/vstudio/en-US/820bf10f-3eaf-43a8-b5ef-b83b2394342c/windowsshowmodal-to-parentowner-window-only-not-entire-application?forum=wpf

我还尝试了多UI线程方法,但这会导致第三方库(caliburn micro & telerik wpf控件)出现问题,因为它们不是为在多个UI线程中使用而构建的。可以让它们与多个UI线程一起工作,但我更喜欢更简单的解决方案……

如果按照所述方式实现对话框,则不能再使用DialogResult属性,因为这将导致“只有在创建窗口并显示为对话框之后才能设置DialogResult”异常。只需实现您自己的属性并使用它。

您需要以下windows API参考:

代码语言:javascript
复制
/// <summary>
/// Enables or disables mouse and keyboard input to the specified window or control. 
/// When input is disabled, the window does not receive input such as mouse clicks and key presses. 
/// When input is enabled, the window receives all input.
/// </summary>
/// <param name="hWnd"></param>
/// <param name="bEnable"></param>
/// <returns></returns>
[DllImport("user32.dll")]
private static extern bool EnableWindow(IntPtr hWnd, bool bEnable);

然后使用以下命令:

代码语言:javascript
复制
// get parent window handle
IntPtr parentHandle = (new WindowInteropHelper(window.Owner)).Handle;
// disable parent window
EnableWindow(parentHandle, false);
// when the dialog is closing we want to re-enable the parent
window.Closing += SpecialDialogWindow_Closing;
// wait for the dialog window to be closed
new ShowAndWaitHelper(window).ShowAndWait();
window.Owner.Activate();

这是在关闭对话框时重新启用父窗口的事件处理程序:

代码语言:javascript
复制
private void SpecialDialogWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
    var win = (Window)sender;
    win.Closing -= SpecialDialogWindow_Closing;
    IntPtr winHandle = (new WindowInteropHelper(win)).Handle;
    EnableWindow(winHandle, false);

    if (win.Owner != null)
    {
        IntPtr parentHandle = (new WindowInteropHelper(win.Owner)).Handle;
        // reenable parent window
        EnableWindow(parentHandle, true);
    }
}

这是实现模式对话行为所需的ShowAndWaitHelper (这会阻止线程的执行,但仍会执行消息循环。

代码语言:javascript
复制
private sealed class ShowAndWaitHelper
{
    private readonly Window _window;
    private DispatcherFrame _dispatcherFrame;
    internal ShowAndWaitHelper(Window window)
    {
        if (window == null)
        {
            throw new ArgumentNullException("window");
        }
        _window = window;
    }
    internal void ShowAndWait()
    {
        if (_dispatcherFrame != null)
        {
            throw new InvalidOperationException("Cannot call ShowAndWait while waiting for a previous call to ShowAndWait to return.");
        }
        _window.Closed += OnWindowClosed;
        _window.Show();
        _dispatcherFrame = new DispatcherFrame();
        Dispatcher.PushFrame(_dispatcherFrame);
    }
    private void OnWindowClosed(object source, EventArgs eventArgs)
    {
        if (_dispatcherFrame == null)
        {
            return;
        }
        _window.Closed -= OnWindowClosed;
        _dispatcherFrame.Continue = false;
        _dispatcherFrame = null;
    }
}
票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2593498

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档