DOBON.NET DOBON.NETプログラミング掲示板過去ログ

DataGridView 編集中→Enter で・・・・

環境/言語:[VS2005 C# Express Edition]
分類:[.NET]

マルチポストしています。

 C# と VB.NET の質問掲示板
 http://bbs.wankuma.com/ #13846 です。
 ルールに沿って、解決した場合は即座に報告します。すみません。

VS2005 C# 始めたばかりです。宜しくお願いします。

フォームに dataGridView と textBox のコントロールが置いてあります。
dataGridView の あるセルを編集し、Enterキーか、TABキーで、編集を確定し
textBox へフォーカスを移動させる方法が判りません。

普通に keyDown イベントで フォーカスをセットすると、編集中で無い時は
フォーカス移動するのですが、編集中の場合、一度下のセルへ移動後(Enterの場合)、
もう一度 Enterキーを押すことで textBox へフォーカスがあたります。
編集中でも、1度のエンターキーで編集を確定して、 textBoxへフォーカスを移動する
ことはできるのでしょうか?????
はじめまして、引っ込んだ(略)と申します。
 お答えいたします。

  私もDataGridViewはほとんど使ったことがないのですが(汗
 とりあえず以下のコードで、ぽん他さんのご希望の動作になりました。
 ※ コードがVBですがご了承下さい。

Private Sub DataGridView1_CellEndEdit(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellEndEdit
TextBox1.Focus()
End Sub

Private Sub DataGridView1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles DataGridView1.KeyDown
Select Case e.KeyCode
Case Keys.Return, Keys.Tab
TextBox1.Focus()
e.Handled = True ' ←この行はなくてもOK
End Select
End Sub

以上です。
引っ込んだ(略)さん

お返事ありがとうございます。
以下のコードで期待した通りフォーカス移動できました。
嬉しいです。助かりました。

実際操作してみて、気になることがありました。
フォーカスは移動するんですが、DataGridViewの選択行が、
↓のレコードへ移動してしまいます。
(SelectionMode は、FullRowSelect で行全体に設定してます)
この、選択行(色)を編集した行のまま留まることは可能なのでしょうか?
そういう物なのでしょうか?

private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
tbox1.Focus();
e.Handled = true;
}
}

private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
tbox1.Focus();
}
再びこちらの掲示板から、お答えいたします(^^。

 前回の私のコード(わんくまさんの掲示板に投稿したコード)に、以下の不具合がありました。
  ・Cellを編集してTextBoxにフォーカスが移動した後、
   Tabキーを使用してフォーカスを移動し、再度DataGridViewがフォーカスを取得した場合に、
   CurrentCellが「画面上で下の位置のCell」のままである。

 この部分を修正したコードです。
 ※ コードがVBですがご了承下さい。m(_ _)m

' ↓Protectedメソッドを使用しているため、
' ↓派生クラスを作成せざるを得ませんでした。
Public Class DataGridViewEx
Inherits DataGridView
' ↓独自に定義したイベント(TextBox1.Focus()をForm内のコードで行うために必要)
Public Event FocusProposing As EventHandler
Protected Overridable Sub OnFocusProposing(ByVal e As EventArgs)
RaiseEvent FocusProposing(Me, e)
End Sub
Dim m_isendedit As Boolean = False
' ↓最後にクリックしたCell、もしくは最後に編集したCellの位置を記憶するためのメンバ。
Dim m_editindex As New Point(-99, -99)
Protected Overrides Sub OnEnter(ByVal e As System.EventArgs)
MyBase.OnEnter(e)
If Me.m_editindex.X >= 0 Then
Me.SetCurrentCellAddressCore(Me.m_editindex.X, Me.m_editindex.Y, False, False, True)
End If
End Sub
Protected Overrides Sub OnCellClick(ByVal e As System.Windows.Forms.DataGridViewCellEventArgs)
MyBase.OnCellClick(e)
Me.m_editindex = New Point(e.ColumnIndex, e.RowIndex)
End Sub
Protected Overrides Sub OnCellEnter(ByVal e As System.Windows.Forms.DataGridViewCellEventArgs)
MyBase.OnCellEnter(e)
If Me.m_isendedit = True Then
Me.m_isendedit = False
' ↓ここではCurrentCellを変更できなかったので、
' ↓画面表示だけをとりあえず変えておき、
' ↓CurrentCellの変更自体はEnterDataGridViewExがフォーカスを取得した時点(OnEnter内)で行う
Me.SetSelectedRowCore(e.RowIndex, False)
Me.SetSelectedRowCore(Me.m_editindex.Y, True)
End If
End Sub
Protected Overrides Sub OnCellEndEdit(ByVal e As System.Windows.Forms.DataGridViewCellEventArgs)
MyBase.OnCellEndEdit(e)
Me.m_isendedit = True
Me.m_editindex = New Point(e.ColumnIndex, e.RowIndex)
Me.OnFocusProposing(EventArgs.Empty)
End Sub
Protected Overrides Sub OnKeyDown(ByVal e As System.Windows.Forms.KeyEventArgs)
MyBase.OnKeyDown(e)
Select Case e.KeyCode
Case Keys.Return, Keys.Tab
Me.OnFocusProposing(EventArgs.Empty)
e.Handled = True ' ←この行はなくてもOK
End Select
End Sub
End Class

以上です。
念のための補足説明です。
 もしご存知の場合は読み飛ばしてください。

 すでにForm上にDataGridViewが貼り付けられている場合は、
 そのDataGridViewをデザイナ上で削除する必要はありませんし、
 DataGridViewExをツールボックスからFormにドロップする必要もありません。
 DataGridViewをDataGridViewExに置き換える際には、
 Form1.Designer.csのコードを2箇所変更すれば、
 DataGridViewのプロパティ等の設定内容を、
 DataGridViewExにそのまま引き継ぐことができます。
 インスタンス名もdataGridView1のままですので、Form1.cs等のコードを書き直す必要もありません。

  1.this.dataGridView1 = new System.Windows.Forms.DataGridView();
        ↓
    this.dataGridView1 = new DataGridViewEx();

  2.private System.Windows.Forms.DataGridView dataGridView1;
        ↓
    private DataGridViewEx dataGridView1;

 C#のコードはこちらになります。(VisualC#2005で動作を確認)

// Form内のコード
private void dataGridView1_FocusProposing(object sender, EventArgs e)
{
this.textBox1.Focus();
}

// DataGridViewExクラス
public class DataGridViewEx : DataGridView
{
public event EventHandler FocusProposing;
protected virtual void OnFocusProposing(EventArgs e){
this.FocusProposing(this, e);
}
bool m_isendedit = false;
Point m_editindex = new Point(-99, -99);
protected override void OnEnter(EventArgs e){
base.OnEnter(e);
if (this.m_editindex.X >= 0){
this.SetCurrentCellAddressCore(this.m_editindex.X, this.m_editindex.Y, false, false, true);
}
}
protected override void OnCellClick(DataGridViewCellEventArgs e){
base.OnCellClick(e);
this.m_editindex = new Point(e.ColumnIndex, e.RowIndex);
}
protected override void OnCellEnter(DataGridViewCellEventArgs e){
base.OnCellEnter(e);
if (this.m_isendedit == true) {
this.m_isendedit = false;
this.SetSelectedRowCore(e.RowIndex, false);
this.SetSelectedRowCore(this.m_editindex.Y, true);
}
}
protected override void OnCellEndEdit(DataGridViewCellEventArgs e){
base.OnCellEndEdit(e);
this.m_isendedit = true;
this.m_editindex = new Point(e.ColumnIndex, e.RowIndex);
this.OnFocusProposing(EventArgs.Empty);
}
protected override void OnKeyDown(KeyEventArgs e){
base.OnKeyDown(e);
if (e.KeyCode == Keys.Return){
int i= this.CurrentCellAddress.Y;
this.SetSelectedRowCore(i, false);
if (i >= 1) { this.SetSelectedRowCore(i - 1, true); }
this.OnFocusProposing(EventArgs.Empty);
e.Handled = true; // ←この行はなくてもOK
}
if (e.KeyCode == Keys.Tab){
this.OnFocusProposing(EventArgs.Empty);
e.Handled = true; // ←この行はなくてもOK
}
}
}

以上です。
2008/02/12(Tue) 09:35:09 編集(投稿者)

他のパターンです。

    public partial class DataGridViewKeyDown : Form
    {
        public DataGridViewKeyDown()
        {
            InitializeComponent();
        }

        private void DataGridViewKeyDown_Load(object sender, EventArgs e)
        {
            // TODO: このコード行はデータを 'testdbDataSet.TEST' テーブルに読み込みます。必要に応じて移動、または削除をしてください。
            this.tESTTableAdapter.Fill(this.testdbDataSet.TEST);
        }

        public void SetFocusToTextBox()
        {
            this.textBox1.Focus();
        }
    }

    // DataGridViewの「列の編集ダイアログ」で、このMyDataGridViewTextBoxColumnを選択すること。
    public class MyDataGridViewTextBoxColumn : DataGridViewTextBoxColumn
    {
        public MyDataGridViewTextBoxColumn()
        {
            base.CellTemplate = new MyDataGridViewTextBoxCell();
        }
    }

    // Cell
    public class MyDataGridViewTextBoxCell : DataGridViewTextBoxCell
    {
        public override Type EditType
        {
            get
            {
                return typeof(MyDataGridViewTextBoxEditingControl);
            }
        }

        protected override void OnKeyDown(KeyEventArgs e, int rowIndex)
        {
            if ((e.KeyCode & Keys.Enter) == Keys.Enter)
            {
                ((DataGridViewKeyDown)this.DataGridView.Parent).SetFocusToTextBox();
            }

            base.OnKeyDown(e, rowIndex);
        }
    }

    public class MyDataGridViewTextBoxEditingControl : DataGridViewTextBoxEditingControl
    {
        protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e)
        {
            if ((e.KeyData & Keys.KeyCode) == Keys.Enter)
            {
                ((DataGridViewKeyDown)this.EditingControlDataGridView.Parent).SetFocusToTextBox();

                //エンターキーでフォーカスが他に行かないようにする。
                this.EditingControlDataGridView.EndEdit();
                return;
            }

            base.OnPreviewKeyDown(e);
        }
    }
お世話になっております。

http://bbs.wankuma.com/ #13846 の方で
一旦解決済みとさせて頂きました。

ありがとうございました。



■No21461に返信(trapemiyaさんの記事)
> 2008/02/12(Tue) 09:35:09 編集(投稿者)
>
> 他のパターンです。
>
> public partial class DataGridViewKeyDown : Form
> {
> public DataGridViewKeyDown()
> {
> InitializeComponent();
> }
>
> private void DataGridViewKeyDown_Load(object sender, EventArgs e)
> {
> // TODO: このコード行はデータを 'testdbDataSet.TEST' テーブルに読み込みます。必要に応じて移動、または削除をしてください。
> this.tESTTableAdapter.Fill(this.testdbDataSet.TEST);
> }
>
> public void SetFocusToTextBox()
> {
> this.textBox1.Focus();
> }
> }
>
> // DataGridViewの「列の編集ダイアログ」で、このMyDataGridViewTextBoxColumnを選択すること。
> public class MyDataGridViewTextBoxColumn : DataGridViewTextBoxColumn
> {
> public MyDataGridViewTextBoxColumn()
> {
> base.CellTemplate = new MyDataGridViewTextBoxCell();
> }
> }
>
> // Cell
> public class MyDataGridViewTextBoxCell : DataGridViewTextBoxCell
> {
> public override Type EditType
> {
> get
> {
> return typeof(MyDataGridViewTextBoxEditingControl);
> }
> }
>
> protected override void OnKeyDown(KeyEventArgs e, int rowIndex)
> {
> if ((e.KeyCode & Keys.Enter) == Keys.Enter)
> {
> ((DataGridViewKeyDown)this.DataGridView.Parent).SetFocusToTextBox();
> }
>
> base.OnKeyDown(e, rowIndex);
> }
> }
>
> public class MyDataGridViewTextBoxEditingControl : DataGridViewTextBoxEditingControl
> {
> protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e)
> {
> if ((e.KeyData & Keys.KeyCode) == Keys.Enter)
> {
> ((DataGridViewKeyDown)this.EditingControlDataGridView.Parent).SetFocusToTextBox();
>
> //エンターキーでフォーカスが他に行かないようにする。
> this.EditingControlDataGridView.EndEdit();
> return;
> }
>
> base.OnPreviewKeyDown(e);
> }
> }
解決済み!
> http://bbs.wankuma.com/ #13846 の方で
> 一旦解決済みとさせて頂きました。

申し訳ありませんが、解決法を書いていただけないでしょうか?後で見た方が分からなくなってしまい可能性がありますので。よろしくお願いいたします。

DOBON.NET | プログラミング道 | プログラミング掲示板