【问题标题】:How to handle KeyEvents in a DataGridViewCell?如何处理 DataGridViewCell 中的 KeyEvent?
【发布时间】:2010-09-13 02:06:34
【问题描述】:

是否存在DataGridViewCellKeydown 事件?
我想要做的是当用户在特定单元格中输入时,他可以按 F1 以获得该特定列的帮助。并且会弹出一些表单...

这是什么活动?

【问题讨论】:

    标签: c# winforms datagridview


    【解决方案1】:

    我在论坛中找到了this 代码,它可以工作。

    private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
    {
       DataGridViewTextBoxEditingControl tb = (DataGridViewTextBoxEditingControl)e.Control;
       tb.KeyPress += new KeyPressEventHandler(dataGridViewTextBox_KeyPress);    
       e.Control.KeyPress += new KeyPressEventHandler(dataGridViewTextBox_KeyPress);
    }
        
    private void dataGridViewTextBox_KeyPress(object sender, KeyPressEventArgs e)
    {
       //when i press enter,bellow code never run?
       if (e.KeyChar==(char)Keys.Enter)
       {
          MessageBox.Show("You press Enter");
       }
    }
    

    【讨论】:

    • 这对我不起作用。按下回车键时不会触发 KeyDown、KeyUp 和 KeyPressed 事件(但是对于字符键它们会触发)。我必须使用 DataGridViewTextBoxEditingControl 对象的 PreviewKeyDown 事件才能捕获 Enter 键。
    【解决方案2】:

    DataGridViewCell 没有任何事件,但是您可以在DataGridView 本身上监听KeyDown 事件,然后查看选择了哪个单元格:

    public void dataGridView_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.F1)
        {
            var selectedCell = dataGridView.SelectedCells[0];
            // do something with selectedCell...
        }
    }
    

    【讨论】:

    • DGV 不会触发来自编辑控件的键盘事件,上述代码无法处理编辑模式下的按键事件。
    【解决方案3】:

    当用户在单元格中键入时,实际上是在为编辑目的而放置在单元格内的控件中键入。例如,字符串列类型实际上会创建一个 TextBox 以在单元格内使用,供用户输入。因此,在进行编辑时,您需要真正挂钩放置在单元格内的 TextBox 的 KeyDown 事件。

    【讨论】:

      【解决方案4】:

      另一种解决方案是

      private void grdDetalle_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
          {
              // Sólo queremos esta funcionalidad para determinadas columnas Clave y Nombre
              if ((grdDetalle.Columns[grdDetalle.CurrentCell.ColumnIndex].Name == "colClaveArticulo") ||
                  (grdDetalle.Columns[grdDetalle.CurrentCell.ColumnIndex].Name == "colNombre"))
              {
                  /// Workarround para que estando editando en las columnas del grid Clave y Nombre
                  /// podamos detectar cuando se dio F4 para lanzar el dialogo de busqueda del
                  /// articulo.
                  e.Control.KeyDown += new KeyEventHandler(dataGridViewTextBox_KeyDown);
                  e.Control.Leave += new EventHandler(dataGridViewTextBox_Leave);
              }
          }
      
          private void dataGridViewTextBox_Leave(object sender, EventArgs e)
          {
      
              if ((grdDetalle.Columns[grdDetalle.CurrentCell.ColumnIndex].Name == "colClaveArticulo") ||
                 (grdDetalle.Columns[grdDetalle.CurrentCell.ColumnIndex].Name == "colNombre"))
              {
                  try
                  {
                      (sender as DataGridViewTextBoxEditingControl).KeyDown -= 
                         new KeyEventHandler(dataGridViewTextBox_KeyDown);
                  }
                  catch (Exception ex)
                  { }
              }
          }
      
          private void dataGridViewTextBox_KeyDown(object sender, KeyEventArgs e)
          {
              // F4 Pressed
              if ((grdDetalle.Columns[grdDetalle.CurrentCell.ColumnIndex].Name == "colClaveArticulo") ||
                 (grdDetalle.Columns[grdDetalle.CurrentCell.ColumnIndex].Name == "colNombre"))
              {
                  if (e.KeyCode == Keys.F4) // 115
                  {
                      MessageBox.Show("Oprimieron F4");
                      e.Handled = true;
                      e.SuppressKeyPress = true;
                  }
              }
          }
      

      【讨论】:

      • 我建议用英文变量名和 cmets 修改你的代码,以便人们更容易理解你在做什么。
      • 我更同意这个解决方案,因为您提供了选择特定列的方法
      【解决方案5】:

      我知道这是一个老问题,但我相信我在投票最多的答案上有所改进。

          IDataGridViewEditingControl _iDataGridViewEditingControl;
          private void SlotTimesDGV_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
          {
              if (_iDataGridViewEditingControl is DataGridViewComboBoxEditingControl)
              {
                  DataGridViewComboBoxEditingControl iDataGridViewEditingControl = _iDataGridViewEditingControl as DataGridViewComboBoxEditingControl;
                  iDataGridViewEditingControl.KeyPress -= SlotTimesDGV_EditingControlShowing_KeyPress;
              }
              if (e.Control is DataGridViewComboBoxEditingControl)
              {
                  DataGridViewComboBoxEditingControl iDataGridViewEditingControl = e.Control as DataGridViewComboBoxEditingControl;
                  iDataGridViewEditingControl.KeyPress += SlotTimesDGV_EditingControlShowing_KeyPress;
                  _iDataGridViewEditingControl = iDataGridViewEditingControl;
              }
          }
      
          private void SlotTimesDGV_EditingControlShowing_KeyPress(object sender, KeyPressEventArgs e)
          {
              MessageBox.Show("");
          }
      

      通过拥有 IDataGridViewEditingControl 的实例变量,您可以删除在移动单元格时会导致重复调用的 KeyPress 事件,并且您的事件不仅限于一种类型的单元格。

      【讨论】:

        【解决方案6】:

        这段代码对我有用。

        Form.KeyPreview = true;
        

        Microsoft Docs 中的描述:“...(KeyPreview) 设置一个值,指示在将事件传递给具有焦点的控件之前表单是否会接收键事件。”。

        【讨论】:

          【解决方案7】:

          覆盖 Form 类的虚函数 ProcessCmdKey 对我有用。

          在 ProcessCmdKey 上返回 true 以防止进一步处理按键。 覆盖所有关键操作的覆盖函数

          例如:

          protected override bool ProcessCmdKey(ref Message msg, Keys keyData) //overridden virtual function
          {
              if (keyData == Keys.Tab) //check to make sure it is the key I am interested in
              { 
                  if (this.dataGridViewKeys.ContainsFocus) //make sure it is on the control, or any child controls, of the one I am interested in
                  {
                      this.dataGridViewKeys.EndEdit(); //do whatever action you want here
                      if (this.dataGridViewKeys.CurrentRow.IsNewRow && this.dataGridViewKeys.Rows.Count > 1)
                          this.dataGridViewKeys.CurrentCell = this.dataGridViewKeys.Rows[this.dataGridViewKeys.Rows.Count - 1].Cells[2];
                      this.txtNoteData.Focus();
                      return true;  //I return true to prevent further handling of the keypress
                  }
              }
              return base.ProcessCmdKey(ref msg, keyData); //return this for keys you do not want to intercept
          }
          

          【讨论】:

            【解决方案8】:

            to this answer:

            在您的解决方案中,您不应忘记取消监听事件

            private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
            {
              tb.KeyUp -= Tb_KeyUp;
            }
            

            在我的解决方案中,我订阅了 KeyUp,而不是 KeyDown,因为我需要替换编辑单元格的值

            DataGridViewTextBoxEditingControl tb { get; set; }
            
            private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
            {
                tb = (DataGridViewTextBoxEditingControl)e.Control;
                CellEditingTB.KeyUp += Tb_KeyUp;
            }
            
            private void Tb_KeyUp(object sender, KeyEventArgs e)
            {
                if (tb != null)
                {
                    if (e.KeyCode == Keys.Decimal)
                    {
                        ..
                    }
                }
            }
            

            【讨论】:

            • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-05-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多