WPF窗口构造函数调用Close触发异常,事件中调用正常的原因咨询
问题分析与解决方案
我来帮你理清这个问题的核心原因,以及对应的解决办法:
为什么构造函数里调用Close()会报错?
当你在GammeDetail的构造函数里调用this.Close()时,窗口对象虽然已经被实例化,但它还没有完成初始化流程,也从未被显示过。此时调用Close()会将窗口标记为已关闭状态,但后续你又调用了ShowDialog()——WPF不允许对一个已经关闭的窗口执行显示操作,所以就抛出了那个异常。
而按钮点击事件里的Close()是完全不同的场景:此时窗口已经完成了所有初始化步骤,并且已经成功显示在界面上,调用Close()是在窗口的生命周期内合法的关闭操作,自然不会有问题。
正确的解决思路
不要在构造函数里直接关闭窗口,而是把你的条形码校验逻辑移到合适的时机,这里给你两种可行方案:
方案1:提前校验,不符合条件就不创建窗口
在调用ShowDialog()之前先做条形码的合法性检查,只有通过了再实例化窗口,逻辑更清晰:
// 在调用窗口的地方先执行校验 string numLot; string numGamme; try { numLot = _barCode.Substring(0, _barCode.Length - 2); numGamme = _barCode.Substring(_barCode.Length - 2); } catch { // 提示用户格式错误,无需创建窗口 MessageBox.Show("无效的条形码格式"); return; } // 校验通过后再创建并显示窗口 GammeDetail gammeDetail = new GammeDetail(numLot, numGamme, userID); gammeDetail.ShowDialog();
同时修改GammeDetail的构造函数,直接接收校验后的参数:
public GammeDetail(string numLot, string numGamme, int userID) { InitializeComponent(); this._numLot = numLot; this._numGamme = numGamme; // 其他初始化逻辑 }
方案2:在窗口Loaded事件中校验并关闭
如果必须在窗口内部做校验,就把逻辑移到Loaded事件里,此时窗口已经完成初始化,调用Close()是合法的:
public GammeDetail(string barcode, int userID) { InitializeComponent(); this.Loaded += GammeDetail_Loaded; this._barCode = barcode; this._userID = userID; } private void GammeDetail_Loaded(object sender, RoutedEventArgs e) { try { this._numLot = _barCode.Substring(0, _barCode.Length - 2); this._numGamme = _barCode.Substring(_barCode.Length - 2); } catch { this.Close(); MessageBox.Show("无效的条形码格式"); } }
两种方案都能避免你遇到的异常,更推荐方案1,它符合单一职责原则,把参数校验和窗口创建的逻辑分离开,代码可读性更高。
内容的提问来源于stack exchange,提问作者Steeven_b




