如何以编程方式从数据网格视图中的一个单元格移动到另一个单元格



我只需要允许在可编辑的数据网格视图单元格中输入一个字符(每隔一列,奇数列,都是可编辑的);如果用户在其中一个单元格中添加了第二个字符,光标应该向下移动到下一个单元格,并将第二个值放在那里(再次按下该键会再次向下移动,依此类推)。如果在网格的底部(第12行),它应该移动到第0行,并向右移动两列。

我试过这样做:

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];
        }
    }
}

DataGridViewCurrentCell属性有一个setter,允许您传入一个新单元格。

解决这个问题的一种方法是处理网格的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(在从网格中检索所需单元格之后)的原则仍然有效。

可以设置单元格的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;

我可能错过了一些资本化,但你明白了。

DGV上的

KeyDown无法工作,因为DataGridViewTextBoxColumn使用了一个就地TextBox控件,该控件使其可见,并及时移动到位进行编辑。

由于所有文本列只有一个现成的TextBox,所以您可以订阅它的KeyDown事件,但获取对该控件的引用可能会有鸡和蛋的问题。

最好使用Form的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);
    }
}

我有一个进程,如果所选单元格位于第一列,它就会轰炸。因此,在该过程的按钮代码中,这是其中的第一个代码:(BTW,我使用网格中的单元格选择)

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

这有效地"选项卡"到下一列,然后我的流程的其余部分就可以工作了。

相关内容

  • 没有找到相关文章

最新更新