【问题标题】:How to detect that a Window has used up its "ShowDialog" call如何检测窗口已用完其“ShowDialog”调用
【发布时间】:2010-11-14 21:25:42
【问题描述】:

在 WPF 中,您只能在窗口上调用 ShowDialog 一次。之后就完成了。

对我来说似乎有点蹩脚,但这是规则。如果你再次调用ShowDialog,你会得到这个异常:

在窗口关闭后无法设置可见性或调用 Show、ShowDialog 或 WindowInteropHelper.EnsureHandle

我想知道的是:我怎样才能获取Window(或UserControl)并检查它是否已经调用了ShowDialog(所以我知道new 之前有一个不同的再次拨打ShowDialog)。

类似这样的:

public void ShowListOfClients()
{
    //    |  This is the method I want to write
    //    V                                          
    RefreshViewIfNeeded(_myWindowOrUserControlThatShowsAList);

    FillWindowWithBusinessData(_myWindowOrUserControlThatShowsAList);
    _myWindowOrUserControlThatShowsAList.ShowDialog();

}

注意:显然,在上面的示例中,每次输入方法时创建一个新的WindowOrUserControlThatShowsAList 会更容易。但请考虑这个问题,而不是愚蠢的例子。

【问题讨论】:

    标签: c# wpf


    【解决方案1】:

    这不是 ShowDialog() 独有的,Show() 也可以。不,没有要检查的 IsDisposed 属性。 IsLoaded 只是解决方案的一半,第一次调用也是错误的。

    第一种方法是只制作一个可以重新显示的对话框:

        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();
        }
    

    【讨论】:

    • 我搞砸了最后一个。想不出一个//say fix。
    • 我喜欢关闭方法的委托。这看起来不错。谢谢!
    • 除了上面的第一个建议特别不适用于模态窗口,即ShowDialog()。它将避免异常,但会导致其他问题,例如无法退出进程,以及在第二次使其可见时无法正确显示窗口。只有第二个建议(即始终重新创建窗口)是可行的。
    • 更改第一个建议,而不是试图避免关闭窗口,它只是跟踪 是否 窗口已关闭 -- 即将属性命名为 IsClosed,然后处理Closed 事件而不是Closing,并在那里将属性值设置为true——这将直接解决所述问题,即“如何检测窗口已用完其“ShowDialog”打电话”
    【解决方案2】:

    那么肮脏的做法是捕获异常。

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

    【讨论】:

    • 我正在使用 MVVM,但如果我按照您的建议进行操作,那么我的模型会创建它支持的视图(有人告诉我 MVVM 对此不以为然)。
    • 如果模型需要在屏幕上更新,它应该触发一个事件。可以通过视图附加此事件。此视图可能是所有者窗口,它将实际查看挂起到单独的对话框中。
    【解决方案3】:

    解决这个问题的简单方法,而不会弄乱 Closing 事件:

    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();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2015-01-27
      • 2011-02-05
      • 1970-01-01
      • 2013-01-13
      • 1970-01-01
      • 1970-01-01
      • 2019-08-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多