バグ調査をしていたところ、DataGridView.DataSoueceをnullで初期化すると、Columnsも初期化される という記事を見つけました。
バグの原因は、記事に書かれている通りでした。(先人に感謝です)
AutoGenerateColumns の設定によって、DataGridView.DataSource に null を設定したときに、Columns が初期化されるかどうかが変わります。
AutoGenerateColumns の値 | DataSource に null を代入したときの挙動 |
---|---|
true | Columns が初期化される(ヘッダーごと消える) |
false | Columns は初期化されない(ヘッダーは残る) |
サンプルプログラムで確認してみる
こういうのは、動かしてみるのが一番分かりやすいのでサンプルプログラムを作りました。
上の表はカラムの自動生成ON => AutoGenerateColumns = true の表です。
下の表はカラムの自動生成OFF => AutoGenerateColumns = false の表です。
それぞれの表の横に DataSource を null にするボタンがあります。
動かしてみましょう。
gif のように上の表(カラムの自動生成ON => AutoGenerateColumns = true)はヘッダーごと消えているのが分かります。
それに対して、下の表(カラムの自動生成OFF => AutoGenerateColumns = false)はヘッダーが残っているのが分かります。
デバッガで DataSource を null にした後を見てみます。
AutoGenerateColumns = true の表は columns の数が0になっています。
対してAutoGenerateColumns = false の表は columns の数が1のままになっていました。
この差により、DataSource = null セット後の挙動に差が出たと考えられます。
いやぁ、なかなかの罠ですね。ヘッダーごとリセットしたい場合は、AutoGenerateColumns の設定値によらず、 Columns.Clear() してあげたほうが良さそうです。
参考にこのサンプルプログラムの Form のコードも載せておきます。
using System;
using System.Data;
using System.Windows.Forms;
namespace DataGridViewTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// 上の表はカラムの自動生成ON
dataGridView1.AutoGenerateColumns = true;
// 上の表にデータをセット
var table1 = new DataTable();
table1.Columns.Add("text");
table1.Rows.Add("カラムを自動生成");
dataGridView1.DataSource = table1;
// 下の表はカラムの自動生成OFF
dataGridView2.AutoGenerateColumns = false;
// 下の表にデータをセット
var table2 = new DataTable();
table2.Columns.Add("text");
table2.Rows.Add("カラムを手動で追加");
dataGridView2.DataSource = table2;
// 下の表のカラムを手動で追加
var textColumn = new DataGridViewTextBoxColumn();
{
textColumn.DataPropertyName = "text";
textColumn.Name = "text";
textColumn.HeaderText = "text";
}
dataGridView2.Columns.Add(textColumn);
}
private void button1_Click(object sender, EventArgs e)
{
dataGridView1.DataSource = null;
}
private void button2_Click(object sender, EventArgs e)
{
dataGridView2.DataSource = null;
}
}
}