WinForm中子窗体的子窗体关闭时如何触发主窗体的对应事件?
问题根因
你代码的核心问题是创建了两个完全独立的frmSearchList实例:
- 主窗体
mainBtnMenuSearch_Click中创建的frmSearchList仅绑定了关闭事件,从来没有被调用Show()显示,属于无效实例 - 实际弹出的搜索结果窗体是搜索窗体
searchByDate_Click中新建的另一个frmSearchList实例,这个实例从未绑定主窗体的frmSearchTriggerEvent事件,自然关闭时不会触发回调
另外你主窗体中frmSearchList是mainBtnMenuSearch_Click的局部变量,你在frmSearchTriggerEvent中访问的这个变量也不是实际运行的实例,就算事件触发也取不到正确的isOpenedProject值。
解决方案
方案1:自定义事件(推荐,松耦合)
这种方案不需要跨窗体传递实例引用,代码可维护性更高:
- 改造搜索结果窗体
frmSearchList,定义公开的关闭通知事件:
public partial class frmSearchList : Form { public bool isOpenedProject { get; set; } // 定义搜索结果关闭的公开事件,直接返回isOpenedProject状态 public event Action<bool> OnSearchResultClosed; public void openProjectByResult_Click(object sender, EventArgs e) { // 原有传递选中结果的代码保留 isOpenedProject = true; this.Close(); } protected override void OnFormClosed(FormClosedEventArgs e) { base.OnFormClosed(e); // 触发事件通知订阅方 OnSearchResultClosed?.Invoke(isOpenedProject); } }
- 改造搜索窗体
frmSearch,把搜索结果的事件对外透传:
public partial class frmSearch : Form { // 对外暴露搜索结果关闭事件 public event Action<bool> OnSearchResultClosed; public void searchByDate_Click(object sender, EventArgs e) { // 原有搜索、传参代码保留 frmSearchList frmSearchList = new frmSearchList(); // 订阅搜索结果窗体的关闭事件 frmSearchList.OnSearchResultClosed += (isOpened) => { OnSearchResultClosed?.Invoke(isOpened); }; frmSearchList.Show(); this.Close(); } }
- 改造主窗体代码,直接订阅事件即可:
public void mainBtnMenuSearch_Click(object sender, EventArgs e) { frmSearch frmSearch = new frmSearch(); // 订阅搜索结果的关闭通知 frmSearch.OnSearchResultClosed += FrmSearch_OnSearchResultClosed; frmSearch.Show(); } private void FrmSearch_OnSearchResultClosed(bool isOpenedProject) { if (isOpenedProject) { loadForm(); } }
方案2:快速修改(直接传递实例,适合小项目)
如果不想调整整体结构,可以直接把实际运行的frmSearchList实例传递给主窗体绑定事件:
- 搜索窗体
frmSearch新增公开属性存储搜索结果实例:
public partial class frmSearch : Form { // 存储实际创建的搜索结果窗体实例 public frmSearchList ResultForm { get; private set; } public void searchByDate_Click(object sender, EventArgs e) { // 原有搜索、传参代码保留 ResultForm = new frmSearchList(); ResultForm.Show(); this.Close(); } }
- 主窗体修改绑定逻辑,给实际运行的实例绑定事件:
public void mainBtnMenuSearch_Click(object sender, EventArgs e) { frmSearch frmSearch = new frmSearch(); // 先订阅搜索窗体的关闭事件,拿到实际的搜索结果实例 frmSearch.FormClosed += (s, args) => { if (frmSearch.ResultForm != null) { // 给真实显示的搜索结果窗体绑定关闭事件 frmSearch.ResultForm.FormClosed += frmSearchTriggerEvent; } }; frmSearch.Show(); } // 回调方法从sender取实例,不要用原来的局部变量 public void frmSearchTriggerEvent(object sender, FormClosedEventArgs e) { var searchList = (frmSearchList)sender; if (searchList.isOpenedProject) { loadForm(); } }
内容的提问来源于stack exchange,提问作者valdrinNereth
相关产品推荐
相关产品推荐

