传递DataGridView至新窗体遇dgv空引用错误,求排查方案
问题原因分析
你遇到的NullReferenceException核心原因是代码执行顺序不对:当LightnessTable的构造函数运行时,dgv属性还没被赋值。
看一下Form1里的执行流程:
- 先实例化
LightnessTable:LightnessTable LightnessForm = new LightnessTable(); - 此时会触发
LightnessTable的构造函数,里面直接调用了DataGridView_Configuration(),试图给dgv绑定事件,但这时候dgv还是null(因为还没执行LightnessForm.dgv = dgv;) - 之后才给
LightnessForm.dgv赋值并添加到控件集合
这就导致构造函数里访问dgv时触发空引用错误。
解决方案
这里提供两种简单可行的修改方案,你可以按需选择:
方案一:通过属性Setter触发配置逻辑
修改LightnessTable中的dgv属性,把事件绑定逻辑放到属性的setter里,确保只有当dgv被赋值后才执行配置:
namespace LightnessComparision { public partial class LightnessTable : Form { private DataGridView _dgv; public DataGridView dgv { get => _dgv; set { _dgv = value; // 赋值完成后再绑定事件 DataGridView_Configuration(); } } public LightnessTable() { InitializeComponent(); // 移除构造函数里的DataGridView_Configuration()调用 } private void DataGridView_Configuration() { dgv.VisibleChanged += DgView_VisibleChanged; } private void DgView_VisibleChanged(object sender, EventArgs e) { DataGridView_PaintCells(); } private void DataGridView_PaintCells() { foreach (DataGridViewRow row in dgv.Rows) { foreach (DataGridViewCell cell in row.Cells) { if (cell.Value == null) continue; // 增加空值判断,避免转换报错 short cellValue = Convert.ToInt16(cell.Value); if (cellValue < -5) { cell.Style.BackColor = Color.Yellow; } else if (cellValue > 5) { cell.Style.BackColor = Color.Black; cell.Style.ForeColor = Color.White; // 加前景色,避免黑色背景看不到文字 } else { // 重置样式,防止重复设置后样式残留 cell.Style.BackColor = dgv.DefaultCellStyle.BackColor; cell.Style.ForeColor = dgv.DefaultCellStyle.ForeColor; } } } } } }
方案二:在Form1中手动触发配置逻辑
把LightnessTable里的DataGridView_Configuration()改成public,然后在Form1中给dgv赋值后再手动调用这个方法:
修改LightnessTable:
// 把private改成public public void DataGridView_Configuration() { dgv.VisibleChanged += DgView_VisibleChanged; }
修改Form1的Button3_Click:
public void Button3_Click(object sender, EventArgs e) { /* SOME LOGIC */ LightnessTable LightnessForm = new LightnessTable(); dgv.DataSource = resulTable; LightnessForm.dgv = dgv; LightnessForm.DataGridView_Configuration(); // 赋值完成后再调用配置 LightnessForm.Controls.Add(dgv); LightnessForm.AutoSize = true; LightnessForm.Show(); }
额外优化建议:用CellFormatting事件替代VisibleChanged
你当前用VisibleChanged来设置单元格样式有局限性——只有控件可见性变化时才会触发,如果后续数据更新,样式不会自动刷新。
推荐使用DataGridView.CellFormatting事件,这是.NET专门为单元格样式格式化设计的事件,每次单元格需要渲染时都会触发,更可靠:
private void DataGridView_Configuration() { // 替换VisibleChanged为CellFormatting dgv.CellFormatting += Dgv_CellFormatting; } private void Dgv_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) { // 跳过表头行 if (e.RowIndex < 0) return; // 空值判断 if (e.Value == null) return; if (short.TryParse(e.Value.ToString(), out short cellValue)) { if (cellValue < -5) { e.CellStyle.BackColor = Color.Yellow; } else if (cellValue > 5) { e.CellStyle.BackColor = Color.Black; e.CellStyle.ForeColor = Color.White; } else { // 重置为默认样式 e.CellStyle.BackColor = dgv.DefaultCellStyle.BackColor; e.CellStyle.ForeColor = dgv.DefaultCellStyle.ForeColor; } } }
注意点
另外,你直接把Form1中的dgv添加到LightnessForm的控件集合里,会导致这个DataGridView从Form1的控件树中移除——因为WinForms控件只能属于一个容器。如果需要在两个窗体同时显示数据,应该传递数据源(比如resulTable),而不是直接移动控件。
内容的提问来源于stack exchange,提问作者Kuba Do
相关产品推荐
相关产品推荐

