如何检测窗口是否已经使用完其“ShowDialog”调用

7
在WPF中,您只能对一个窗口调用一次ShowDialog。之后就无法再使用了。
这对我来说似乎有点糟糕,但这就是规则。如果您再次调用ShowDialog,则会出现以下异常:

Cannot set Visibility or call Show, ShowDialog, or WindowInteropHelper.EnsureHandle after a Window has closed

我想知道的是:如何检查Window(或实际上是UserControl)是否已经调用了ShowDialog(以便在再次调用ShowDialog之前新建另一个)。
类似于这样的东西:
public void ShowListOfClients()
{
    //    |  This is the method I want to write
    //    V                                          
    RefreshViewIfNeeded(_myWindowOrUserControlThatShowsAList);

    FillWindowWithBusinessData(_myWindowOrUserControlThatShowsAList);
    _myWindowOrUserControlThatShowsAList.ShowDialog();

}

注意:显然,在上面的例子中,每次进入方法时创建一个新的WindowOrUserControlThatShowsAList会更容易。但请考虑更复杂的情况。

3个回答

9

这不仅适用于ShowDialog(),Show()也会这样做。并且,没有IsDisposed属性可以检查。IsLoaded只是一个半解决方案,因为它在第一次调用时也为false。

第一种方法是创建一个可以重新显示的对话框:

    public bool CloseAllowed { get; set; }

    private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
        if (!CloseAllowed) {
            this.Visibility = System.Windows.Visibility.Hidden;
            e.Cancel = true;
        }
    }

下一个步骤是明确跟踪对象引用的健康状况:
    private Window1 win = new Window1();   // say

    private void button1_Click(object sender, RoutedEventArgs e) {
        if (win == null) {
            win = new Window1();
            win.Closing += delegate { win = null; };
        }
        win.ShowDialog();
    }

我弄错了最后一个。想不出该怎么修复。 - Hans Passant
我喜欢将委托分配给关闭方法。看起来不错。谢谢! - Vaccano
除了上面的第一个建议不适用于模态窗口,即使用 ShowDialog()。它可以避免异常,但会引起其他问题,例如无法退出进程,以及第二次显示窗口时无法正确显示。只有第二个建议(即始终重新创建窗口)是可行的。 - Peter Duniho
将第一个建议更改为不是试图避免关闭窗口,而是简单地跟踪窗口是否关闭 - 即命名属性为IsClosed,然后处理Closed事件而不是Closing,并在那里将属性值设置为true - 这将直接解决所述问题,即“如何检测窗口是否已使用其“ShowDialog”调用”。 - Peter Duniho

3

有一种不太好的方式是捕获异常来处理。

更好的方式是使用ShowDialog方法显示一个窗口,并在函数返回时销毁(失去引用等)该窗口。视图不应与模型紧密耦合(你正在使用MVVM吗?),因此为每个客户端视图创建新的可视对象不应成为问题。


我正在使用MVVM,但如果我按照您的建议去做,那么我的Model将会创建它所支持的View(这是我听说MVVM不赞成的)。 - Vaccano
如果一个模型需要在屏幕上更新,它应该触发一个事件。这个事件可以被视图所附加。这个视图可能是拥有者窗口,它将实际的查看操作挂起到一个单独的对话框中。 - Guy

0

在不干扰关闭事件的情况下解决这个问题的简单方法:

public partial class MainWindow
{
    private SomeCustomWindow _someCustomWindow;

    public MainWindow()
    {
        InitializeComponent();
    }

    private void OnOpenCustomWindowButtonClick(object sender, RoutedEventArgs e)
    {
        if (_someCustomWindow != null)
            _someCustomWindow.Close();
        _someCustomWindow = new SomeCustomWindow();

        _someCustomWindow.ShowDialog();
    }

    private void OnWindowClosing(object sender, CancelEventArgs e)
    {
        if (_someCustomWindow!= null)
            _someCustomWindow.Close();
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接