You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动