C# MDI 多文档窗体(父子窗体、布局平铺、单例显示)全套笔记
2026/7/5 14:50:32 网站建设 项目流程

一、MDI 核心概念

1. 什么是 MDI

MDI(多文档界面):一个主窗体中可以嵌套多个子窗体,所有子窗体只能在主窗体内部显示,不会独立弹出悬浮窗口。

常见软件场景:Word、Excel、PS 多文档窗口。

2. 核心属性与方法

  • 窗体.IsMdiContainer = true:设置当前窗体为MDI父容器(必须手动勾选/设置)

  • 子窗体.MdiParent = this:指定子窗体的所属父窗体

  • this.MdiChildren:获取当前父窗体所有已打开的子窗体集合

  • LayoutMdi():批量排布子窗体布局


二、MDI 三种经典布局枚举

布局枚举

效果

MdiLayout.TileVertical

垂直平铺(左右均分)

MdiLayout.TileHorizontal

水平平铺(上下均分)

MdiLayout.Cascade

层叠平铺(堆叠窗口)


三、基础功能:打开多个子窗体 + 自动布局

一次性打开 Form2、Form3,并设置垂直平铺布局

private void 打开窗体ToolStripMenuItem_Click(object sender, EventArgs e) { // 打开子窗体2,并绑定父容器 Form2 f2 = new Form2(); f2.MdiParent = this; f2.Show(); // 打开子窗体3,修改背景色并绑定父容器 Form3 f3 = new Form3(); f3.MdiParent = this; f3.BackColor = Color.Red; f3.Show(); // 所有子窗体 垂直平铺 LayoutMdi(MdiLayout.TileVertical); }

四、布局切换功能

private void 设置窗体ToolStripMenuItem_Click(object sender, EventArgs e) { // 切换为水平平铺 LayoutMdi(MdiLayout.TileHorizontal); }

五、核心重难点:通用 Open 方法(子窗体单例逻辑)

1. 功能需求

  • 重复点击菜单,不会重复创建同类型窗体

  • 如果当前已经打开该类型窗体:隐藏所有窗体、激活并显示原有窗体

  • 如果是新类型窗体:隐藏所有旧窗体、展示新窗体

  • 实现始终只显示一个子窗体的效果

2. 完整核心源码

/// <summary> /// MDI子窗体通用打开方法(去重+单例+切换逻辑) /// </summary> public void Open(Form f) { // 1. 遍历所有已打开的MDI子窗体 foreach (var item in this.MdiChildren) { // 判断:即将打开的窗体类型 == 已存在的子窗体类型 if (f.GetType() == item.GetType()) { // 隐藏所有子窗体 foreach (Form child in this.MdiChildren) { child.Hide(); } // 显示并激活当前已有窗体(不重复new) item.Show(); item.Activate(); return; } } // 2. 走到这里说明:当前没有同类型窗体 // 隐藏所有旧窗体 foreach (Form child in this.MdiChildren) { child.Hide(); } // 绑定父容器并展示新窗体 f.MdiParent = this; f.Show(); }

3. 逻辑拆解

  1. GetType() 类型对比:判断窗体是否为同一个窗体类,解决重复实例化问题

  2. 存在同类型窗体:全部隐藏 → 激活旧窗体 → return 终止方法,不创建新对象

  3. 不存在同类型窗体:隐藏所有旧窗体 → 创建并展示新窗体


六、菜单调用封装方法

// 打开Form2(单例) private void 打开窗体1ToolStripMenuItem_Click(object sender, EventArgs e) { Open(new Form2()); } // 打开Form3(单例) private void 打开窗体2ToolStripMenuItem_Click(object sender, EventArgs e) { Open(new Form3()); }

七、MDI 两套写法对比

写法一(基础版)

每次点击都 new 新窗体,会出现多个同类型子窗体叠加

写法二(进阶封装版)

通过类型判断 + 隐藏激活,保证同类窗体永远唯一,企业项目标准写法


八、高频易错点

  • 主窗体必须开启IsMdiContainer = true,否则无法嵌套子窗体

  • 必须赋值MdiParent = this,否则窗体独立弹出,不属于子窗体

  • == 对比窗体对象会一直创建新窗体,必须用GetType() 对比类型

  • 不写 return 会继续执行创建新窗体,无法实现单例

  • MdiChildren 只能获取当前存活、已加载的子窗体


九、MDI 背诵口诀

主窗开启容器态,子窗绑定父窗体;

MdiChildren遍历子,类型判断去重替;

先藏后显保唯一,布局平铺横竖齐;

封装通用Open法,多文档界面稳如一。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询