C# WinForm MDI父窗体向子窗体传值的实现方法
问题根因
现有代码存在4个核心问题导致传值失败:
- 子窗体只定义了接收1个字符串参数的构造函数,菜单唤起时调用的无参
new Child()找不到匹配构造,无法正常编译 - ON按钮点击事件中虽然创建了带设备名的子窗体实例,但既没有设置MdiParent、也没有调用
Show()方法,这个实例根本不会在MDI容器中展示 - 两种唤起逻辑完全独立:如果子窗体已经通过菜单打开,点击ON按钮时新创建的子窗体实例和已打开的实例不是同一个,数据无法同步到已展示的窗体上
- 子窗体构造函数只预留了设备名1个参数的接收通道,设备型号、生产日期两个字段没有传值入口,且代码存在变量拼写错误、语句缺分号的语法问题
修正实现
第一步:改造子窗体代码
保留无参构造兼容菜单唤起场景,新增公开的设备信息更新方法,同时支持初始化传值和已打开窗体的实时数据更新,避免重复创建实例:
public partial class Child : Form { // 无参构造,供菜单唤起场景使用 public Child() { InitializeComponent(); } /// <summary> /// 加载/更新设备展示信息 /// </summary> /// <param name="deviceName">设备名称</param> /// <param name="deviceModel">设备型号</param> /// <param name="manufactureDate">生产日期</param> public void UpdateDeviceDisplay(string deviceName, string deviceModel, string manufactureDate) { name_lbl.Text = deviceName; model_lbl.Text = deviceModel; date_lbl.Text = manufactureDate; } }
第二步:修正父窗体全局定义与ON按钮逻辑
先把三个设备信息定义为父窗体全局变量方便复用,点击ON按钮时优先复用已打开的子窗体实例,不存在再新建,统一传值:
// 父窗体全局设备信息字段 private string deviceName; private string deviceModel; private string manuFacturedDate; private void btnOn_Click(object sender, EventArgs e) { // 赋值设备信息 deviceName = "Notebook520220624"; deviceModel = "520220627"; manuFacturedDate = "220627"; Child targetForm = null; // 检查子窗体是否已打开 if (Application.OpenForms["Child"] is Child openedForm) { targetForm = openedForm; } else { // 子窗体未打开则新建实例 targetForm = new Child(); targetForm.MdiParent = this; targetForm.Show(); } // 新、旧实例统一调用方法更新展示数据 targetForm.UpdateDeviceDisplay(deviceName, deviceModel, manuFacturedDate); targetForm.Focus(); }
第三步:修正父窗体菜单唤起逻辑
保持原有单实例判断逻辑,可按需选择是否在菜单唤起时自动加载已存储的设备信息:
private void DeviceInfomationToolStripMenuItem_Click(object sender, EventArgs e) { if (Application.OpenForms["Child"] is Child deviceInfo) { deviceInfo.Focus(); // 需要菜单唤起时自动加载已存设备信息就放开下方注释 // if (!string.IsNullOrEmpty(deviceName)) // { // deviceInfo.UpdateDeviceDisplay(deviceName, deviceModel, manuFacturedDate); // } return; } deviceInfo = new Child(); deviceInfo.MdiParent = this; // 需要新建子窗体时自动带上已存设备信息就放开下方注释 // if (!string.IsNullOrEmpty(deviceName)) // { // deviceInfo.UpdateDeviceDisplay(deviceName, deviceModel, manuFacturedDate); // } deviceInfo.Show(); }
注意事项
- 必须把子窗体的
Name属性设置为Child,否则Application.OpenForms["Child"]无法匹配到已打开的实例,会出现重复创建窗体的问题 - 这种公开方法传值的方式比重载构造函数更适配MDI场景,不管窗体是已经初始化展示、还是未创建,都能随时同步数据,不需要维护多套构造逻辑
内容的提问来源于stack exchange,提问作者Lha
相关产品推荐
相关产品推荐

