我只需要允许一个字符被input到可编辑的datagridview单元格(每隔一列,奇数编号)是可编辑的; 如果用户在其中一个单元格中添加第二个字符,则光标应该移动到下一个单元格,并将该第二个值放在那里(再次按下该键将向下移动,等等)。 如果在网格的底部(第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列。
从纵观者的回答来看,这是我迄今为止所得到的,但我不知道如何推进到下一个单元格。
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); }
谢谢大家 这正是我用来让它工作得非常好(我仍然希望能够让用户简单地按住键,并在后续的单元格中持续input该值):
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]; } } }
DataGridView
的CurrentCell
属性有一个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;
我可能错过了那里的一些资本,但你明白了。
DGD上的KeyDown将无法工作,因为DataGridViewTextBoxColumn使用原地的TextBox控件,使其可视化,并及时就地编辑。
由于所有文本列只有一个就地文本框,因此您可以订阅其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); } }