C#子窗体向主窗体回传文本数据问题:空引用异常求助
解决System.NullReferenceException问题的方案
咱们先直接戳破问题根源:你搞反了事件的订阅逻辑,而且在子窗体的按钮点击事件里错误地把sender转换成Form1——但实际用户点击按钮时,sender是按钮控件本身,不是主窗体实例,这才导致了空引用异常。
错误原因拆解
看你主窗体这段代码:
CharAdded += uif.btnAdd_Click; //Call Event if (CharAdded != null) { CharAdded(this, new EventArgs()); }
你把主窗体的CharAdded事件和子窗体的btnAdd_Click方法绑定了,触发事件时是主窗体调用这个方法,此时sender确实是主窗体实例。但当用户真正点击子窗体的Add按钮时,这个方法的sender是Button控件,你用Form1 mainForm = sender as Form1;转换,自然得到null,调用mainForm.GetData()就会抛出空引用异常。
正确的实现方式
我们应该让子窗体在用户输入完成后主动触发事件传递数据,主窗体订阅这个事件来接收并处理数据,步骤如下:
1. 简化Character类(可选,让代码更简洁)
public class Character { // 用自动属性代替手动实现的私有字段 public string Name { get; set; } public override string ToString() { return Name; } }
2. 修改UserInputForm子窗体代码
在子窗体里定义一个事件,当用户点击添加按钮时触发,把输入的名字传出去:
public partial class UserInputForm : Form { // 定义事件,用于传递输入的角色名称 public event Action<string> OnCharacterAdded; public UserInputForm() { InitializeComponent(); } private void btnAdd_Click(object sender, EventArgs e) { // 先校验输入不为空 if (string.IsNullOrWhiteSpace(txtName.Text)) { MessageBox.Show("请输入角色名称!"); return; } // 触发事件,传递输入的名字(空安全调用) OnCharacterAdded?.Invoke(txtName.Text); // 可选:添加完成后关闭子窗体 this.Close(); } }
3. 修改主窗体Form1的代码
在打开子窗体时,订阅子窗体的事件,接收数据并添加到列表:
public partial class Form1 : Form { public List<Character> charList = new List<Character>(); public Form1() { InitializeComponent(); } private void GetData(string name) { Character c = new Character(); c.Name = name; charList.Add(c); // 这里可以更新UI,比如把列表绑定到ListBox: // listBoxCharacters.DataSource = null; // listBoxCharacters.DataSource = charList; } private void btnCreateChar_Click(object sender, EventArgs e) { UserInputForm uif = new UserInputForm(); // 订阅子窗体的事件,接收数据并处理 uif.OnCharacterAdded += (characterName) => { GetData(characterName); }; // 用ShowDialog模态打开子窗体,或者用Show非模态,看你的需求 uif.ShowDialog(); } }
为什么这样能解决问题?
- 事件流向更合理:子窗体负责收集用户输入,在用户确认后触发事件传递数据;主窗体负责订阅事件,接收数据并处理。
- 不再依赖
sender转换获取主窗体实例,彻底避免了空引用的风险。 - 代码逻辑更清晰,符合WinForms中父子窗体交互的常规做法。
内容的提问来源于stack exchange,提问作者Chad E
相关产品推荐
相关产品推荐

