如何确定WPF窗口是否为模态窗口?

时间:2008-12-15 16:31:35

标签: .net wpf

找出窗口是否以模态方式打开的最简单方法是什么?

澄清:

我打开一个叫

的窗口
myWindow.ShowDialog();

我有一个“OK”的页脚&如果窗口以模态方式打开,我只想显示“取消”按钮。现在我意识到我可以通过这样做来设置属性:

myWindow.IsModal = true;
myWindow.ShowDialog();

但我希望窗户本身能够做出决定。我想检查窗口的Loaded事件是否是模态的。

更新

IsModal属性实际上不存在于WPF窗口中。这是我创建的一个属性。 ShowDialog()阻止当前线程。

我猜我可以通过检查当前线程是否被阻止来确定是否通过ShowDialog()打开了Window。我该怎么做呢?

9 个答案:

答案 0 :(得分:30)

来自http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/c95f1acb-5dee-4670-b779-b07b06afafff/

“System.Windows.Interop.ComponentDispatcher.IsThreadModal可以告诉您调用线程当前是否正在运行模态hwnd。”

答案 1 :(得分:29)

每当WPF窗口是模态对话框时,都会有一个私有字段_showingAsDialog。您可以通过反射获得该值并将其合并到扩展方法中:

public static bool IsModal(this Window window)
{
    return (bool)typeof(Window).GetField("_showingAsDialog", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(window);
}

当窗口显示为模态(ShowDialog)时,该值设置为true,窗口关闭后设置为false。

答案 2 :(得分:4)

好吧,既然我的最后一个想法被否决了,我证明了这一点。这工作 - 我在一个新的WPF应用程序中测试它,所以我知道它的工作原理:

在我的主窗口(Window1)Loaded事件中,我做了:

Dim frm As New Window2
frm.ShowDialog()

在我的Window2中,我隐藏了ShowDialog()方法

Private _IsModal As Boolean = False 'This will be changed in the IsModal method

Public Property IsModal() As Boolean
  Get
    Return _IsModal
  End Get
  Set(ByVal value As Boolean)
    _IsModal = value
  End Set
End Property

Public Shadows Sub ShowDialog()
  IsModal = True
  MyBase.ShowDialog()
End Sub

在我的Loaded事件中,我然后触发了一个消息框以确保IsModal属性从False更改为True并且它给了我True,所以我知道IsModal已设置。 MyBase.ShowDialog()然后强制基类作为Modal加载。阴影允许我们覆盖默认行为,即使ShowDialog()方法未被声明为可覆盖。

虽然它不是“自我确定”,但它不要求你从外部传递任何布尔值,并且不需要你从外部设置IsModal,它将其设置在自身内部,它可以从外部访问如果你这样选择使用它。它仅在我们使用ShowDialog()方法加载时设置值,而不是在使用Show()方法时加载。我怀疑你会找到一种更简单的方法。

答案 3 :(得分:2)

这是一个转换器片段,用于在ShowDialog方法调用窗口时隐藏元素:

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        Window window = value as Window;
        if (window != null)
        {               
            var showingAsDialogFieldInfo = typeof(System.Windows.Window).GetField("_showingAsDialog",
                BindingFlags.NonPublic | BindingFlags.Instance);
            if ((bool) showingAsDialogFieldInfo.GetValue(window) == false)
            {
                return Visibility.Visible;
            }
        }
        return Visibility.Hidden;
    }

答案 4 :(得分:0)

模态窗口将停止处理直到它关闭。

此示例显示显示非模态窗口

dim f as myWindow
f.show
someOtherMethod()

在此示例中,someOtherMethod在窗口启动后立即运行。

此示例显示显示模式1:

dim f as myWindow
f.showDialog
someOtherMethod()

在这个例子中,someOtherMethod()在ShowDialog方法返回之前不会运行(这意味着模态窗口已经关闭)

由于澄清而编辑: 覆盖ShowDialog并传入一个布尔值。

dim f as MyWindow
f.ShowDialog(true)

然后在窗口

Public Function Shadows ShowDialog(myVar as boolean) As Boolean
    if myVar then ShowButtons()
    return mybase.ShowDialog()
End Function 

答案 5 :(得分:0)

在Windows中使用UI自动化,我想出了类似的东西:

void Window2_Loaded(object sender, RoutedEventArgs e)
{
    var hwnd = new System.Windows.Interop.WindowInteropHelper(this).Handle;
    var el = AutomationElement.FromHandle(hwnd);

    Object oPattern = null;

    if (el.TryGetCurrentPattern(WindowPattern.Pattern, out oPattern))
    {
        var pattern = oPattern as WindowPattern;

        this.Title = pattern.Current.IsModal.ToString();
    }
}

但这似乎不起作用。有一个IsModal属性http://msdn.microsoft.com/en-us/library/system.windows.automation.provider.iwindowprovider.ismodal.aspx必须有一个正确的方法来获取窗口的AutomationElement,并通过自动化检查它的IsModal属性是否为真。

答案 6 :(得分:0)

您还可以创建一个继承自 Window 的新类 Dialog 。在Dialog类中创建一个私有变量 IsDialog ,并使用new覆盖 ShowDialog 函数。调用ShowDialog时,将IsDialog变量设置为true:

public class Dialog : Window
{
    private bool IsDialog;

    new public bool? ShowDialog()
    {
        IsDialog = true;
        return base.ShowDialog();
    }
}

答案 7 :(得分:-1)

是否可以检查窗口的父级以查看它是否已禁用?我不确定这是否可以通过WPF API完成,但如果没有别的你可以获得WPF窗口的HWND,通过Win32 P / Invoke(或其他)获取其父,然后检查它是否是否被禁用。

绝对不是一个干净的方法,但似乎它可以工作。

答案 8 :(得分:-1)

如果没有使用ShowDialog()打开窗口,则

Window不允许您为Window.DialogResult设置值。因此,您可以尝试设置Window.DialogResult并查看它是否引发异常。