初のまともな投稿は.NETネタ。
何かと問題が多いWindows FormsのDataGridViewですが、こいつのせいでまた迷惑こうむりました。
現象としては「先頭行が勝手に消える」というもの。
サンプルコードをば。
まずは、新規プロジェクトを追加し、フォームに適当なBindingSourceとDataGridViewを追加します。
また、コード側にはNameプロパティとAgeプロパティを持ったPersonクラスを作っておきます。
で、BindingSourceのDataSourceをPersonクラスにして、DataGridViewのDataSourceはBindingSourceにする。
この状態で実行すると、フォームにはName列とAge列がある行追加可能なDataGridViewが表示されるはず。
ここでButtonを1個追加し、クリック処理に下記のような処理を記述します。
private void button1_Click(object sender, EventArgs e)
{
bindingSource1.DataSource = new List<Person>();
dataGridView1.Focus();
dataGridView1.AllowUserToAddRows = false;
bindingSource1.DataSource = new List<Person>()
{
new Person(){Name = "一郎", Age = 10},
new Person(){Name = "次郎", Age = 9},
};
}
これで、ボタンを押すと画面のグリッドに一郎さんと次郎さんが表示され、行追加が不可能になります。
…が。なぜか次郎さんを選択した瞬間に一郎さんが消えてしまいます。
これ、キモになる条件は
①BindingSourceを使ってデータ連結されている新規行追加可能なグリッドで、
②データソースに空のリストが設定されている状態で、
③データグリッドにフォーカスを当て、そのままフォーカスを外さずに、
④データグリッドのAllowUserToAddRowsプロパティをfalseに変更し、
⑤その後、データソースに空ではないリストを設定した場合
という感じです。
ざっくりとした理屈ですが、新規行追加状態のグリッドにフォーカス当たると、
グリッドの内部的なステータスが「新規行追加中」になります。
その状態で新規行追加を封じることによって、内部ステータスと実際の状態の間に不整合が発生し、
あとで一郎さんのRowValidatingが発生した際に、新規行の登録をキャンセルしたものとみなされて行が消える、
というのがおおまかな流れのようです。
ちなみにデータソースにList<T>ではなくBindingList<T>を使用していた場合はこの現象発生しません。
まあ、BindingSource使うならBindingList<T>使えってことなんでしょうかね。
DataGridViewはちょっと条件が揃うと急に謎な動きをして未だに怖いですね。
WPFのDataGridよりはだいぶマシだと思いますがw
0 件のコメント:
コメントを投稿