【问题标题】:Cannot call Close when Closing event is override覆盖关闭事件时无法调用关闭
【发布时间】:2018-02-27 14:51:23
【问题描述】:

在我的MainWindow 构造函数中,我忽略了Closing 事件,因为我需要调用另一个方法来执行某些任务,例如:

    public MainWindow()
    {
        InitializeComponent();

        Closing += (x, y) =>
        {
            y.Cancel = true;
            _discard = true;
            CheckSettings();
        };
    }

    public void CheckSettings(bool x)
    {
       if(x)
         Close(); 
    }

Close 行我得到:

窗口关闭后无法设置可见性或调用 show 或 showdialog

为什么??

【问题讨论】:

  • 您不能从 Closing 事件处理程序调用 Close。您可能需要让CheckSettings 返回一个布尔值,使用它的返回值设置y.Cancel,并从CheckSettings 中删除Close 调用
  • 在窗口关闭时关闭窗口没有意义,如果框架没有做任何特殊的检测也会导致无限循环。与其问“为什么会出错”,不如问问自己为什么要这样做。
  • @vc74 你能举个例子吗

标签: c# wpf


【解决方案1】:

(根据您的评论要求...) 您不能从 Closing 事件处理程序调用 Close。

如果判断表单是否可以关闭的逻辑在CheckSettings中实现:

public MainWindow()
{
    InitializeComponent();

    Closing += (sender, args) =>
    {
        args.Cancel = !CheckSettings();
        ...
    };
}

public bool CheckSettings()
{
   // Check and return true if the form can be closed
}

【讨论】:

    【解决方案2】:

    在您从事件处理程序返回(即调用 CheckSettings)之前,您使用的 UI 框架可能不会评估您命名为 yEventArgs 的内容并设置 @ 987654326@开。

    如果您使用的是 WPF,例如,Close 方法最终会调用另一个名为 VerifyNotClosing 的方法(通过 InternalClose),在撰写本文时它看起来像这样:

    private void VerifyNotClosing()
    {
        if (_isClosing == true)
        {
            throw new InvalidOperationException(SR.Get(SRID.InvalidOperationDuringClosing));
        }
    
        if (IsSourceWindowNull == false && IsCompositionTargetInvalid == true)
        {
            throw new InvalidOperationException(SR.Get(SRID.InvalidCompositionTarget));
        }
    }
    

    相关位是第一个if,它检查名为_isClosing 的成员变量,如果表单正在关闭,则抛出异常。 InternalClose 方法对 EventArgs 的 Cancel 属性的状态做出反应事件处理程序已被调用:

    CancelEventArgs e = new CancelEventArgs(false);
    try
    {
        // The event handler is called here
        OnClosing(e);
    }
    catch
    {
        CloseWindowBeforeShow();
        throw;
    }
    
    // The status of the .Cancel on the EventArgs is not checked until here
    if (ShouldCloseWindow(e.Cancel))
    {
        CloseWindowBeforeShow();
    }
    else
    {
        _isClosing = false;
        // 03/14/2006 -- hamidm
        // WOSB 1560557 Dialog does not close with ESC key after it has been cancelled
        //
        // No need to reset DialogResult to null here since source window is null.  That means
        // that ShowDialog has not been called and thus no need to worry about DialogResult.
    }
    

    上面的代码(来自InternalClose 方法)调用VerifyNotClosing 这就是为什么在第一个调用完成之前对Close 的后续调用会导致抛出异常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-16
      • 1970-01-01
      • 1970-01-01
      • 2014-05-23
      • 1970-01-01
      • 2020-03-09
      相关资源
      最近更新 更多