|
■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の方法では、確定行として処理できますが、ソート用の列を用意する必要があります。
必要に応じて使い分けてみてください。
|