MDI窗体关闭问题解决一例
由于工作忙,很久没有来这里了,久违了。
背景:
MDI子窗体中的一个是导航窗体,该窗体定义了CLOSING事件处理:检测窗体的关闭标志是否允许,如果不允许则取消关闭操作,这样保证了导航窗体的不被关闭而永久存在。
问题:
当关闭MDI容器窗体的时候,因为其中一个子窗体的关闭事件被取消了,所以关闭动作失败,导致要关闭MDI主窗体只能通过调用Application的Exit方法来实现真正的关闭操作。
解决:
当关闭MDI子窗体的时候,由于导航窗体有关闭控制处理,可能会取消窗体的关闭操作,因此设想:在主窗体关闭的时候,设置导航窗体的关闭标志为允许关闭,这样主窗体就不会因为子窗体的关闭被取消而取消了。但实验结果是不可行:所有子窗体的CLOSING事件都在主窗体的CLOSING事件之前触发,当在主窗体进行可关闭标志的设置的时候,对主窗体已经是无效的了。感觉很沮丧,总不能让用户执行两次关闭操作吧?使用Application.Exit来处理,也感觉不理想,便采用对导航窗体的可关闭标志进行置位后再次调用关闭函数来实现。
经过跟踪处理,发现,主窗体和所有的子窗体共用同一个CLOSING事件参数(System.ComponentModel.CancelEventArgs),因此导致只要任何一个窗体(包括主窗体和子窗体)取消的关闭事件,那么整个关闭操作就失败。基于这个原因,在主窗体的CLOSING事件里面,设置CANCEL=false轻松解决问题(因为主窗体的CLOSING事件永远都是最后一个被触发)。
以上解决方案又会带来一个漏洞:除了导航窗口外,如果有其它窗体确实需要取消关闭操作将会导致失败。对于这个问题,可以采用以下两个方案处理:
1——
在主窗体的CLOSING处理中,强制CANCEL标记复位,然后执行每个子窗体是否确实允许关闭的检测再来设置CANCEL标志。
这个方案不好的地方是主窗体必须知道子窗体是否定义了指定的函数,导致主窗体对子窗体的实现类型存在依赖
2——
基于方案1中存在的问题,考虑:各子窗体是否真的可以被关闭的标志置于Tag属性中,这样,子窗体与主窗体之间只要达成这个协议就可以很好的解决这个问题。
相关代码:
子窗体Closing事件代码:















主窗体Closing事件处理代码:




























【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述