5

編集可能なdatagridviewセルに入力できるのは1文字だけにする必要があります(他のすべての列、奇数番号の列は編集可能です)。これらのセルの1つにユーザーが2番目の文字を追加した場合、カーソルは次のセルに移動し、その2番目の値をそこに置く必要があります(そのキーをもう一度押すと、下に移動します)。グリッドの下部(12行目)にある場合は、行0に移動し、2列も右に移動する必要があります。

私はこれをやってみました:

private void dataGridViewPlatypus_KeyDown(object sender, KeyEventArgs e) {
    var currentCell = dataGridViewPlatypus.CurrentCell;
    int currentCol = currentCell.ColumnIndex;
    int currentRow = currentCell.RowIndex;
    if (currentCell.Value.ToString().Length > 0) {
        if (currentRow < 11) {
            dataGridViewPlatypus.CurrentCell.RowIndex = currentRow+1;
        } else if (currentRow == 11) {
            currentCell.RowIndex = 0;
            currentCell.ColumnIndex = currentCell.ColumnIndex + 2;
            dataGridViewPlatypus.CurrentCell = currentCell;
        }
    }
}

...しかし、RowIndexとColumnIndexは読み取り専用であるため、割り当てることができないエラーメッセージが表示されます。

では、どうすればこれを達成できますか?

警告:現在、編集可能な最後の列の下部にある場合は、列1に移動するためのロジックも追加する必要があることを知っています。

アップデート

tergiverの答えから、これは私がこれまでに得たものですが、次のセルに進む方法がわかりません。

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
    if (this.ActiveControl == dataGridViewPlatypus)
    {
        var currentCell = dataGridViewPlatypus.CurrentCell;
        if (currentCell.Value.ToString().Length == 1) 
        {
            ;//Now what?
        }
    }
    return base.ProcessCmdKey(ref msg, keyData);
}

更新2

皆さんありがとう; これは、私がそれをほぼ機能させるために使用しているものです(ユーザーがキーを押したままにして、その値を後続のセルに継続的に入力できるようにしたい):

private void dataGridViewPlatypus_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) {
    int columnIndex = (((DataGridView)(sender)).CurrentCell.ColumnIndex);
    if (columnIndex % 2 == 1) {
        e.Control.KeyDown -= TextboxNumeric_KeyDown;
        e.Control.KeyDown += TextboxNumeric_KeyDown;
        e.Control.KeyUp -= TextboxNumeric_KeyUp;
        e.Control.KeyUp += TextboxNumeric_KeyUp;
    }
}

private void TextboxNumeric_KeyDown(object sender, KeyEventArgs e) {
    var tb = sender as TextBox;
    if (tb != null) {
        tb.MaxLength = 1;
    }
}

// TODO: Now need to find a way to be able to just press down once
private void TextboxNumeric_KeyUp(object sender, KeyEventArgs e) {
    var tb = sender as TextBox;
    if (tb != null && tb.TextLength >= 1) {
        if (dataGridViewPlatypus.CurrentCell.RowIndex != dataGridViewPlatypus.Rows.Count - 1) {
            dataGridViewPlatypus.CurrentCell = dataGridViewPlatypus[
                dataGridViewPlatypus.CurrentCell.ColumnIndex,
                dataGridViewPlatypus.CurrentCell.RowIndex + 1];
        } else { // on last row
            this.dataGridViewPlatypus.CurrentCell = this.dataGridViewPlatypus.CurrentCell.ColumnIndex !=    dataGridViewPlatypus.Columns.Count - 1 ? this.dataGridViewPlatypus[this.dataGridViewPlatypus.CurrentCell.ColumnIndex    + 2, 0] : this.dataGridViewPlatypus[1, 0];
        }
    }
}
4

4 に答える 4

3

CurrentCellプロパティにはDataGridViewセッターがあり、新しいセルを渡すことができます。

この問題への1つのアプローチEditingControlShowingは、グリッドのイベントを処理KeyPressし、次のように編集コントロールにハンドラーをアタッチすることです。

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{                
    if ((int)(((System.Windows.Forms.DataGridView)(sender)).CurrentCell.ColumnIndex) == 1)
    {
        e.Control.KeyPress += TextboxNumeric_KeyPress;
    }
}

次に、キープレスハンドラーに次のようになります。

private void TextboxNumeric_KeyPress(object sender, KeyPressEventArgs e)
{
    TextBox tb = sender as TextBox;
     if (tb.TextLength >= 5)
     {
         dataGridView1.CurrentCell = dataGridView1[dataGridView1.CurrentCell.ColumnIndex + 1, dataGridView1.CurrentCell.RowIndex];
     }
}

上記のロジックはもちろんあなたのケースには正しくありませんが、(グリッドから目的のセルを取得した後)新しいCurrentCellを渡すという原則は有効です。

于 2012-08-31T12:29:14.793 に答える
1

DataGridViewTextBoxColumnはインプレースのTextBoxコントロールを使用しているため、DGVのKeyDownは機能しません。このコントロールは、編集に間に合うように表示され、所定の位置に移動します。

すべてのテキスト列にインプレースTextBoxが1つしかないため、KeyDownイベントをサブスクライブできますが、そのコントロールへの参照を取得する際に鶏が先か卵が先かという問題が発生する可能性があります。

フォームのProcessCmdKeyオーバーライドを使用して、そこでこのロジックを実行することをお勧めします。キーダウンが発生したら、DGVがActiveControlであるかどうかを確認し、現在のセルがテキストセルであるかどうかを確認し、セルにすでに文字が含まれているかどうかを確認してから、キーの処理を許可する前に現在のセルを変更します。

更新-テイク2

using System;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;

class Item
{
    public string A { get; set; }
    public string B { get; set; }
    public string C { get; set; }
    public string D { get; set; }
}

class Form1 : Form
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

    DataGridView dataGridViewPlatypus;

    public Form1()
    {
        ClientSize = new Size(480, 260);
        Controls.Add(dataGridViewPlatypus = new DataGridView
        {
            Dock = DockStyle.Fill,
            DataSource = Enumerable.Range(1, 10).Select(i => new Item { A = "", B = "", C = "", D = "" }).ToList(),
        });
    }

    [DllImport("User32.dll")]
    extern static int PostMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
    {
        if (msg.Msg == 256) // WM_KEYDOWN
        {
            if (this.ActiveControl == dataGridViewPlatypus.EditingControl)
            {
                var currentCell = dataGridViewPlatypus.CurrentCell;
                if (currentCell.OwningColumn is DataGridViewTextBoxColumn && dataGridViewPlatypus.EditingControl.Text.Length > 0)
                {
                    int rowIndex = currentCell.RowIndex;
                    int columnIndex = currentCell.ColumnIndex;

                    if (++columnIndex >= dataGridViewPlatypus.Columns.Count)
                    {
                        columnIndex = 0;
                        if (++rowIndex >= dataGridViewPlatypus.Rows.Count)
                            rowIndex = 0;
                    }

                    dataGridViewPlatypus.CurrentCell = dataGridViewPlatypus[columnIndex, rowIndex];
                    PostMessage(dataGridViewPlatypus.Handle, msg.Msg, msg.WParam, msg.LParam);
                    return true; // Don't process this message, we re-sent it to the DGV
                }
            }
        }
        return base.ProcessCmdKey(ref msg, keyData);
    }
}
于 2012-08-30T22:34:56.327 に答える
1

セルには、Selected設定できるプロパティがあります。列と行のインデックスでセルにアクセスするだけです。

私はあなたがただできると信じています

dgView.rows[0].cells[0].selected = true

これにより、(0,0)または最初の行、最初の列が交差するセルが得られます。または、次のように行を取得できます。

それがクラスだと思います->DataGridViewRow row = dgView.rows[0]

その後

row[0].cells[0].Selected = true

       Column 1  Column 2
Row 1 [this guy][        ]
Row 2 [        ][        ]

編集:

次のセルを取得するには、次のようにします。

sameRow.cells[currentCell.ColumnIndex+1].Selected = true;

私はそこでいくつかの大文字化を逃したかもしれません、しかしあなたは要点を理解します。

于 2012-08-30T22:35:10.207 に答える
1

選択したセルが1列目にある場合に爆撃するプロセスがあります。したがって、そのプロセスのボタンのコードでは、これが最初のコードです:(ところで、グリッドでセル選択を使用します)

if (dgvGrid.CurrentCell.ColumnIndex == 0) // first column
    dgvGrid.Rows[dgvGrid.CurrentCell.RowIndex].Cells[1].Selected = true;

これは効果的に次の列に「タブ」し、その後、残りのプロセスが機能します。

于 2018-07-19T22:11:19.053 に答える