none
DataGridViewの新規行でデータ入力した際、すぐにその行を有効にする方法 RRS feed

  • 質問

  • いつも大変お世話になっています。

    開発環境: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

    2015年10月1日 7:59

回答

すべての返信

  • 基本的には、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/

    2015年10月1日 9:05
    モデレータ
  • 早々のご回答、ありがとうございます。

    返信が遅くなり申し訳ありません。

    昨日、「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

    2015年10月2日 2:15
  • 正規のやり方がわからないので、

    暫定的に、無理やり、

    入力が変更された時点で、

    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

    2015年10月2日 5:57
  • 少しテストしてみましたが、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
    2015年10月2日 6:27
    モデレータ
  • テストしてくださったんですね。

    お時間とっていただきありがとうございました。

    お蔭様で、うまく動作しています。

    参考サイトは私も見た記憶があるのですが、

    ”DirectCast(DataGridView1.CurrentRow.DataBoundItem, DataRowView).EndEdit()”

    この部分のコーディングがうまくいかず、放り出してしまってました。

    大変お手間をおかけして申し訳ありませんでした。

    今後とも、ご指導よろしくお願いいたします。

    なお、いったん”回答としてマーク”をチェックさせていただいたのですが、

    操作ミスでチェックがつかず、再度チェックしてもエラーになっています。

    対処法をご存知でしたら、チェックを有効にしていただけますでしょうか。


    kizakura_ui

    2015年10月2日 7:32