如何传递EventHandler给面板内子窗体以启用父窗体按钮
问题根源梳理
- 初始版本错误原因:你给
childForm做了面板嵌入配置后,又单独新实例化了一个FormLogin对象frmlgn,事件绑定在这个新实例上,调用Show()的也是这个新实例,和已经嵌入面板的childForm完全是两个不同对象,所以要么弹出独立窗口,要么事件不触发。 - 临时方案的潜在风险:if分支里你又新实例化了
frmlgn,但activeForm赋值的还是传进来的childForm,后续你对activeForm做关闭、取值等操作时,操作的都不是实际显示在面板里的登录窗体,会出现逻辑异常;而且判断窗体用Name匹配非常不严谨,重命名窗体类就会失效。
简洁规范实现方案
核心逻辑是直接对传入的childForm做类型转换,不需要额外实例化新的窗体对象,公共逻辑不需要重复编写,代码如下:
private void OpenChildForm(Form childForm, object btnSender) { // 先关闭已有激活窗体 if (activeForm != null) activeForm.Close(); ActivateButton(btnSender); // 公共嵌入配置 childForm.TopLevel = false; childForm.FormBorderStyle = FormBorderStyle.None; childForm.Dock = DockStyle.Fill; this.panelDesktopPane.Controls.Add(childForm); this.panelDesktopPane.Tag = childForm; // 仅对登录窗体做事件绑定,用模式匹配避免CS1061错误 if (childForm is FormLogin frmlgn) { frmlgn.DataAvailable += new EventHandler(child_DataAvailable); } // 公共显示逻辑 childForm.BringToFront(); childForm.Show(); activeForm = childForm; // 标题栏按钮公共配置 lblTitle.Text = childForm.Text; btnClose.Visible = true; btnMaximize.Visible = true; btnMinimize.Visible = true; btnClose.BringToFront(); btnMaximize.BringToFront(); btnMinimize.BringToFront(); }
方案说明
- 用
is模式匹配直接把传入的childForm转换为FormLogin类型,仅匹配成功时才绑定事件,不会出现CS1061编译错误 - 全程只操作传入的同一个
childForm对象,不会出现多实例混乱,也不会触发TopLevel相关异常 - 公共逻辑只写一次,后续新增其他需要特殊事件绑定的子窗体,只需要加else if分支做对应类型匹配即可,易扩展。
内容的提问来源于stack exchange,提问作者Dave
相关产品推荐
相关产品推荐

