トップ回答者
DataGridViewの新規行でデータ入力した際、すぐにその行を有効にする方法

質問
-
いつも大変お世話になっています。
開発環境:Win7 x86 Visual Studio 2013 C#
DataGridViewの新規行での入力についてご教授ください。
下記のように、BindingSource 経由でDataGridViewにバインディングしています。
dataSource.DataSource = dataTable; //BindingSourceが読み書きするデータ集合としてDataTableを設定してやる dataSource.DataMember = ""; //DataSourceにDataTableを設定するなら空にする bindingNavigator1.BindingSource = dataSource;//カレント位置を制御するデータとしてBindingSourceを設定してやる dataGridView1.DataSource = dataSource;//DataGridViewで表示するデータとしてBindingNavigatorを設定してやる。
DataGridViewの構成は、起動後に作成していきます。
例えば、TextBoxColumnが2列のDataGridViewを作成します。
新規行が1行作られます。
先頭のセルでデータを入力すると、2行目が追加されます(AllowUserToAddRows = true)。
しかし、1行目を有効にするためには、いったん2行目に移動する必要があります。
この移動をすることなく、データ入力した時点で1行目を有効にする方法はありますでしょうか?
なお、「データ入力した時点」とは、以下を意味します。
TextBoxColumnの場合は、Tabキーなどで別の列に移動した時点。
ComboBoxColumnの場合は、リストからデータ選択された時点。
(※ComboBoxColumnのデータ確定については、
「DataGridView内のコンボボックス選択時、バインド先のDataTableを即更新する方法」という質問でご回答いただいています。)
以上、よろしくお願いいたします。
kizakura_ui
回答
-
少しテストしてみましたが、CommitEditも必要なくて、以下の2行だけで大丈夫かもしれません。
dataGridView1.EndEdit(); ((DataRowView)dataGridView1.CurrentRow.DataBoundItem).EndEdit();
(参考)
DataGridViewのLostFocus時にデータが更新できない事がある
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=35999&forum=7★良い回答には回答済みマークを付けよう! MVP - .NET http://d.hatena.ne.jp/trapemiya/
- 回答としてマーク kizakura_ui 2015年10月2日 7:10
すべての返信
-
基本的には、CommitEditメソッドを使えば良いように思います。CommitEditメソッドを実行するタイミングは、CellValidatedやCellEndEditイベントなどが考えられます。
DataGridView.CommitEdit メソッド
https://msdn.microsoft.com/ja-jp/library/system.windows.forms.datagridview.commitedit(v=vs.110).aspx★良い回答には回答済みマークを付けよう! MVP - .NET http://d.hatena.ne.jp/trapemiya/
-
早々のご回答、ありがとうございます。
返信が遅くなり申し訳ありません。
昨日、「DataGridView内のコンボボックス選択時、バインド先のDataTableを即更新する方法」で
trapemiyaさんにご指導いただき解決したのが、下記のコードです。
(一番下のイベント、dataGridView1_CurrentCellDirtyStateChanged()内でCommitEdit()を実行しています)
今回の問題も、コンボボックス選択時という限定はありますが、このコードのままで解決するはず、と考えてよろしいでしょうか?
今のところ、新規行でなければうまくいくのですが、
コンボボックス4列の構成で、全くの新規行から始めるとうまくいきません。
先頭セルでリストから選択すると2行目が追加され、行数を調べてみると
dataGridView1.Rows.Count = 2
dataTable.Rows.Count = 0
となっています。
何かお気づきの点がありましたら、重ねてご指導、よろしくお願いいたします。
// ---------------------------------------------------------------------------------- // コンボボックスの選択が変更された時、カードイメージを更新するための実装↓↓↓↓↓↓ // ---------------------------------------------------------------------------------- /// <summary> /// 編集中の行番号 /// </summary> /// <remarks></remarks> private int _editingRow; private DataGridViewComboBoxEditingControl dataGridViewComboBox = null; /// <summary> /// セルが編集中になった時の処理 /// </summary> /// <param name="sender">イベントの発生元</param> /// <param name="e">イベントの情報</param> /// <remarks>編集中のTextBoxEditingControlにKeyPressイベント設定</remarks> private void dataGridView1_EditingControlShowing( object sender, DataGridViewEditingControlShowingEventArgs e) { //表示されているコントロールがDataGridViewComboBoxEditingControlか調べる if (e.Control is DataGridViewComboBoxEditingControl) { DataGridView dgv = (DataGridView)sender; //編集のために表示されているコントロールを取得 this.dataGridViewComboBox = (DataGridViewComboBoxEditingControl)e.Control; //CurrentCellDirtyStateChangedイベントハンドラを追加 dataGridView1.CurrentCellDirtyStateChanged += new EventHandler(dataGridView1_CurrentCellDirtyStateChanged); _editingRow = dgv.CurrentRow.Index; } } //CellEndEditイベントハンドラ private void DataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e) { //CurrentCellDirtyStateChangedイベントハンドラを削除 if (this.dataGridViewComboBox != null) { dataGridView1.CurrentCellDirtyStateChanged -= new EventHandler(dataGridView1_CurrentCellDirtyStateChanged); this.dataGridViewComboBox = null; } } //DataGridViewに表示されているコンボボックスの //CurrentCellDirtyStateChangedイベントハンドラ private void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e) { // DataTableに情報セット dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit); // カードイメージの更新 dataGridView1_Update(_editingRow, false); // 即カードイメージ更新 } // -------------------------------------------------------------------------------- // コンボボックスの選択が変更された時、カードイメージを更新するための実装↑↑↑↑↑ // --------------------------------------------------------------------------------
kizakura_ui
-
正規のやり方がわからないので、
暫定的に、無理やり、
入力が変更された時点で、
DataGridViewの行数がDataTableより2行以上多く、かつ、カレント行が新規行の一つ上の行の場合に限り、
カレント行を新規行に移動させ、すぐまた元の行に戻す、という処理を追加しました。
結果、カレント行は有効になりました。
正しい方法がありましたら、またご指導よろしくお願いいたします。
//DataGridViewに表示されているコンボボックスの //CurrentCellDirtyStateChangedイベントハンドラ private void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e) { // DataTableに情報セット dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit); // DataGridViewの行数がDataTableより2行以上多い時 if (dataGridView1.Rows.Count >= (dataTable.Rows.Count + 2)) { // カレント行が新規行の一つ上の行の時 if (dataGridView1.CurrentRow.Index == (dataGridView1.Rows.Count - 2)) { // 新規行へ移動 dataGridView1.CurrentCell = dataGridView1[dataGridView1.CurrentRow.Index, dataGridView1.CurrentRow.Index + 1]; // 元の行へ戻る dataGridView1.CurrentCell = dataGridView1[dataGridView1.CurrentRow.Index, dataGridView1.CurrentRow.Index - 1]; } } // カードイメージの更新 dataGridView1_Update(_editingRow, false); // 即カードイメージ更新 }
kizakura_ui
-
少しテストしてみましたが、CommitEditも必要なくて、以下の2行だけで大丈夫かもしれません。
dataGridView1.EndEdit(); ((DataRowView)dataGridView1.CurrentRow.DataBoundItem).EndEdit();
(参考)
DataGridViewのLostFocus時にデータが更新できない事がある
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=35999&forum=7★良い回答には回答済みマークを付けよう! MVP - .NET http://d.hatena.ne.jp/trapemiya/
- 回答としてマーク kizakura_ui 2015年10月2日 7:10
-
テストしてくださったんですね。
お時間とっていただきありがとうございました。
お蔭様で、うまく動作しています。
参考サイトは私も見た記憶があるのですが、
”DirectCast(DataGridView1.CurrentRow.DataBoundItem, DataRowView).EndEdit()”
この部分のコーディングがうまくいかず、放り出してしまってました。
大変お手間をおかけして申し訳ありませんでした。
今後とも、ご指導よろしくお願いいたします。
なお、いったん”回答としてマーク”をチェックさせていただいたのですが、
操作ミスでチェックがつかず、再度チェックしてもエラーになっています。
対処法をご存知でしたら、チェックを有効にしていただけますでしょうか。
kizakura_ui