C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[2]: DataGridViewの最終行にレコードを追加する方法


(過去ログ 143 を表示中)

[トピック内 3 記事 (1 - 3 表示)]  << 0 >>

■84204 / inTopicNo.1)  DataGridViewの最終行にレコードを追加する方法
  
□投稿者/ うみ (1回)-(2017/05/30(Tue) 18:52:33)

分類:[C#] 

お世話になります。

バインドされているDataGridViewにレコードを追加するため、
以下方法で行えたのですが、

------------------------------
DataTable dt = (DataTable)DataGridView.DataSource;
DataRow dr = dt.NewRow();

dr["hoge"] = "1";
dr["fuga"] = "2";
dr["piyo"] = "3";

dt.Rows.Add(dr);
------------------------------

DataGridViewでソートが行われている場合、グリッドのソートが有効となり、
最終行に追加されません。

グリッドのソートを無効化せず、最終行に追加する方法を教えていただけませんか?



引用返信 編集キー/
■84206 / inTopicNo.2)  Re[1]: DataGridViewの最終行にレコードを追加する方法
□投稿者/ 魔界の仮面弁士 (1295回)-(2017/05/31(Wed) 01:02:17)
No84204 (うみ さん) に返信
> DataTable dt = (DataTable)DataGridView.DataSource;

右辺は dataGridView1.DataSource などにしておかないと、
型名と変数名が被ってややこしいことになりますがそれはさておき。


> DataGridViewでソートが行われている場合、グリッドのソートが有効となり、
> 最終行に追加されません。

今回のケースでいえば、「グリッドのソート」が行われている場合、
dt.DefaultView.Sort プロパティが設定された状態になります。

DataGridView への表示順は、dt.DefaultView の列挙順と等しいため、
dt.Rows.Add(dr); を呼び出してしまうと、直ちにソート結果に反映されることになります。


> グリッドのソートを無効化せず、最終行に追加する方法を教えていただけませんか?

【案1】
dataGridView1.DataSource に対して DataTable を直接バインドしている現状では、
登録するデータも dt.DefaultView.Sort に沿った形の DataRow として
用意する必要があります。

といっても、登録するデータは "1", "2", "3" のままにしておきたいでしょうから、
この場合はソート専用に補助列を設けておき(DataGridView には表示させない列)、
そこに、最終行になるような値を登録するといった手法で凌げるでしょう。

この方法では、グリッドのソートを複数列で行うことになるため、
実際には DataGridView の SortCompare イベントのハンドリングを行うなどの
追加の手間が発生します。大袈裟なので、個人的にはお勧めはしません。

そのかわり、最終行以外(途中に挿入させるなど)といった芸当さえも可能となります。



【案2】
dataGridView1.DataSource に対して DataTable や DataSet を直接バインドさせず、
dataGridView1.DataSource に BindingSource を割り当て、それを中継させている場合は

 var newRow = (DataRowView)bindingSource1.AddNew();
 newRow["hoge"] = "1";
 newRow["fuga"] = "2";
 newRow["piyo"] = "3";
 // newRow.EndEdit();

のようにすることで、グリッド末尾に追加させることができます。

なおこの手法では、bindingSource1.AddNew() を呼び出した時点で、
DataGridView のカーソル行(CurrentRow)が、追加された行へと移ります。

また、AddNew した直後は、その行は DataGridView 上からは見えているものの、
まだ DataTable に対しては割り当てられていない状態となっています。
(すなわち、dr.RowState が Detached の状態であるということです)
https://msdn.microsoft.com/ja-jp/library/ww3k31w0.aspx

この未割当の提案行は、DataGridView のカーソル行が別の行に移ったり、
あるいは newRow.EndEdit(); が呼び出されるなどした時点で確定され、
ようやく DataTable にも割り当てられることになります。

そして確定されたと同時に、dr.RowState が Added へと変わり、
DataGridView 上での表示位置も、最終行ではなく本来のソート位置へと遷移します。



【案3】
dataGridView1.DataSource に対して new DataView(dataTable1) をバインドしていた場合も、
案2と同様の処理方法で対処できます。

 var newRow = dataView1.AddNew();
 newRow["hoge"] = "1";
 newRow["fuga"] = "2";
 newRow["piyo"] = "3";
 // newRow.EndEdit();

ただし、案2とは異なり、末尾に提案行が追加された後でも、
DataGridView のカーソル行(CurrentRow)が移らないという違いがあります。

このため、「ソートされた本来の行位置」に移動するまでの確定タイミングに
ズレが生じることになります。



【案4】
dataGridView1.DataSource に対してバインドされるデータが、
DataTable、DataSet、DataView、BindingSource のいずれであったとしても
案2と同様の動作をさせるのがこの方法です。

 CurrencyManager cm = (CurrencyManager)this.BindingContext[dataGridView1.DataSource, dataGridView1.DataMember];
 cm.AddNew();
 var newRow = (DataRowView)cm.Current;
 newRow["hoge"] = "1";
 newRow["fuga"] = "2";
 newRow["piyo"] = "3";
 // cm.EndCurrentEdit();



案2〜4では、提案行が確定されて DataTable の Rows に追加された時点で
ソートされた行位置に移ってしまうことになります。

案1の方法では、確定行として処理できますが、ソート用の列を用意する必要があります。

必要に応じて使い分けてみてください。
引用返信 編集キー/
■84211 / inTopicNo.3)  Re[2]: DataGridViewの最終行にレコードを追加する方法
□投稿者/ うみ (4回)-(2017/05/31(Wed) 10:34:10)
魔界の仮面弁士 様

ご教示いただき、ありがとうございました。

案4で実装することにしました。

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -