为何已关闭的MDI子窗体仍被检测到?如何正确管控子窗体状态?
解决MDI子窗体关闭后仍存在于MdiChildren集合的问题
我明白你遇到的困扰:明明已经调用this.Close()关闭了子窗体,但遍历MdiChildren时它还在,导致判断逻辑出错,甚至重复创建窗体。这其实是MDI子窗体的默认行为在搞鬼,咱们一步步来解决。
为什么关闭后的窗体还在MdiChildren里?
默认情况下,MDI子窗体调用Close()时,并不会被彻底销毁(Dispose),而是被隐藏了。系统会自动将窗体的Visible设为false,但它仍然保留在MdiChildren集合中。这就是你调试时还能找到它的核心原因。
你的需求的正确实现思路
你要做的是:关闭所有非"Sell"的子窗体,如果"Sell"窗体已经存在(不管是显示还是隐藏)就显示它,不存在则新建。咱们分两步实现:
1. 安全关闭非目标子窗体
直接遍历MdiChildren并修改集合(关闭窗体)可能会引发异常,所以先把要关闭的窗体收集到列表里,再逐个处理,同时过滤掉已经销毁的窗体:
// 先筛选出需要关闭的有效窗体(非Sell且未被销毁) var formsToClose = this.MdiChildren .Where(form => !form.Name.Equals("Sell", StringComparison.OrdinalIgnoreCase) && !form.IsDisposed) .ToList(); foreach (var form in formsToClose) { form.Close(); // 如果希望彻底释放资源,避免留在集合里,可以调用Dispose form.Dispose(); }
2. 查找并显示/Sell窗体
接下来,检查是否存在存活的"Sell"窗体,存在就显示(并带到前台),不存在则新建:
// 查找未被销毁的Sell窗体 var existingSellForm = this.MdiChildren .FirstOrDefault(form => form.Name.Equals("Sell", StringComparison.OrdinalIgnoreCase) && !form.IsDisposed); if (existingSellForm != null) { existingSellForm.Show(); existingSellForm.BringToFront(); // 可选:把窗体带到最上层,方便用户操作 } else { // 新建Sell窗体并设置为MDI子窗体 var newSellForm = new SellForm(); // 替换成你的Sell窗体类名 newSellForm.Name = "Sell"; newSellForm.MdiParent = this; newSellForm.Show(); }
额外优化:让Sell窗体关闭时彻底销毁(可选)
如果你希望关闭Sell窗体时,它能从MdiChildren中彻底消失,可以在Sell窗体的FormClosing事件里修改默认行为:
private void SellForm_FormClosing(object sender, FormClosingEventArgs e) { // 取消系统默认的隐藏行为,改为销毁窗体 e.Cancel = false; this.Dispose(); }
这样下次遍历MdiChildren时,这个窗体就会因为IsDisposed=true被过滤掉,不会干扰你的判断。
内容的提问来源于stack exchange,提问作者Fabián Romo
相关产品推荐
相关产品推荐

