.net 如何从 DataGridView 数据单元格中获取按键、按键事件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/325677/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 10:41:56  来源:igfitidea点击:

How to get keypressed, keydown events from DataGridView data cells

.netdatagridviewkeyboard-events

提问by Viesturs

I need to receive the key press events during cell editing in DataGridViewcontrol.

我需要在DataGridView控制单元格编辑期间接收按键事件。

From what I have found on the net the DataGridViewis designed to pass all key events from DataGridViewto the cell editing control and you cannot get these events easily.

从我在网上找到的内容来看,DataGridView它旨在将所有关键事件从DataGridView单元格编辑控件传递到单元格编辑控件,并且您无法轻松获取这些事件。

I found this piece of codethat traps those events for DataGridcontrol, but that does not work for DataGridView.

我发现这段代码可以捕获这些事件以进行DataGrid控制,但这不适用于DataGridView.

采纳答案by Viesturs

Finally figured out. There are two parts of this puzzle - getting keys from cell editing control and getting keys from the DataGridView itself. Here's my code. To use it, you just need to subscribe to the custom event: keyPressHook.

终于想通了。这个难题有两个部分 - 从单元格编辑控件获取键和从 DataGridView 本身获取键。这是我的代码。要使用它,您只需要订阅自定义事件:keyPressHook

class KeyPressAwareDataGridView : DataGridView
{

    protected override void OnControlAdded(ControlEventArgs e)
    {
        this.subscribeEvents(e.Control);
        base.OnControlAdded(e);
    }

    protected override void OnControlRemoved(ControlEventArgs e)
    {
        this.unsubscribeEvents(e.Control);
        base.OnControlRemoved(e);
    }

    protected override bool ProcessDataGridViewKey(KeyEventArgs e)
    {
        bool procesedInternally = false;

        if (this.keyPressHook != null)
        {
            this.keyPressHook(this, e);
            procesedInternally = e.SuppressKeyPress;
        }

        if (procesedInternally)
        {
            return true;
        }
        else
        {
            return base.ProcessDataGridViewKey(e);
        }
    }


    private void subscribeEvents(Control control)
    {
        control.KeyDown += new KeyEventHandler(this.control_KeyDown);
        control.ControlAdded += new ControlEventHandler(this.control_ControlAdded);
        control.ControlRemoved += new ControlEventHandler(this.control_ControlRemoved);

        foreach (Control innerControl in control.Controls)
        {
            this.subscribeEvents(innerControl);
        }
    }

    private void unsubscribeEvents(Control control)
    {
        control.KeyDown -= new KeyEventHandler(this.control_KeyDown);
        control.ControlAdded -= new ControlEventHandler(this.control_ControlAdded);
        control.ControlRemoved -= new ControlEventHandler(this.control_ControlRemoved);

        foreach (Control innerControl in control.Controls)
        {
            this.unsubscribeEvents(innerControl);
        }
    }

    private void control_ControlAdded(object sender, ControlEventArgs e)
    {
        this.subscribeEvents(e.Control);
    }

    private void control_ControlRemoved(object sender, ControlEventArgs e)
    {
        this.unsubscribeEvents(e.Control);
    }

    private void control_KeyDown(object sender, KeyEventArgs e)
    {
        if (this.keyPressHook != null)
        {
            this.keyPressHook(this, e);
        }
    }

    public event KeyEventHandler keyPressHook;

}

回答by Eren Aygunes

Try this:

尝试这个:

class KeyPressAwareDataGridView : DataGridView
{
    protected override void OnControlAdded(ControlEventArgs e)
    {
        SubscribeEvents(e.Control);
        base.OnControlAdded(e);
    }

    protected override void OnControlRemoved(ControlEventArgs e)
    {
        UnsubscribeEvents(e.Control);
        base.OnControlRemoved(e);
    }

    private void SubscribeEvents(Control control)
    { 
        control.KeyPress += new KeyPressEventHandler(control_KeyPress);
        control.ControlAdded += new ControlEventHandler(control_ControlAdded);
        control.ControlRemoved += new ControlEventHandler(control_ControlRemoved);

        foreach (Control innerControl in control.Controls)
        {
            SubscribeEvents(innerControl);
        }
    }

    private void UnsubscribeEvents(Control control)
    {
        control.KeyPress -= new KeyPressEventHandler(control_KeyPress);
        control.ControlAdded -= new ControlEventHandler(control_ControlAdded);
        control.ControlRemoved -= new ControlEventHandler(control_ControlRemoved);

        foreach (Control innerControl in control.Controls)
        {
            UnsubscribeEvents(innerControl);
        }
    }

    private void control_ControlAdded(object sender, ControlEventArgs e)
    {
        SubscribeEvents(e.Control);
    }

    private void control_ControlRemoved(object sender, ControlEventArgs e)
    {
        UnsubscribeEvents(e.Control);
    }

    private void control_KeyPress(object sender, KeyPressEventArgs e)
    {
        // Apply your logic here whether this is the key pressed event you need.
        // (e.g. "if(SelectedCells != null)")
        MessageBox.Show(e.KeyChar.ToString());
    }
}

回答by Viesturs

Or, for those of use that DON'T want to create our own DataGridView for such occassions; there's this method (in C++): It uses the EditingControlShowing Event of the DataGridView.

或者,对于那些不想为这种情况创建我们自己的 DataGridView 的用户;有这个方法(在 C++ 中):它使用 DataGridView 的 EditingControlShowing 事件。

private: System::Boolean fIsNonNumeric;
private: static System::Windows::Forms::KeyEventHandler^ EventKeyDown = nullptr;
private: static System::Windows::Forms::KeyPressEventHandler^ EventKeyPress = nullptr;
private: System::Void dataGridView_KeyDown(System::Object^  sender, System::Windows::Forms::KeyEventArgs^  e) 
{
  fIsNonNumeric= false;

  // Determine whether the keystroke is a number from the top of the keyboard.
  if ( e->KeyCode < Keys::D0 || e->KeyCode > Keys::D9 )
  {
    // Determine whether the keystroke is a number from the keypad.
    if ( e->KeyCode < Keys::NumPad0 || e->KeyCode > Keys::NumPad9 )
    {
      // Determine whether the keystroke is a backspace.
      if ( e->KeyCode != Keys::Back )
      {
        // A non-numerical keystroke was pressed.
        // Set the flag to true and evaluate in KeyPress event.
        fIsNonNumeric = true;
      }
    }
  }
}

private: System::Void dataGridView_KeyPress(System::Object^  sender, System::Windows::Forms::KeyPressEventArgs^  e) 
{
  // Should we stop the character from being entered...?
  if ( fIsNonNumeric == true )
    e->Handled = true;
}

private: System::Void dataGridView_Machines_EditingControlShowing(System::Object^  sender, System::Windows::Forms::DataGridViewEditingControlShowingEventArgs^  e) 
{
  if (nullptr == EventKeyDown)
    EventKeyDown = (gcnew System::Windows::Forms::KeyEventHandler( this, &ProjectForm::dataGridView_KeyDown ));

  if (nullptr == EventKeyPress)
    EventKeyPress = (gcnew System::Windows::Forms::KeyPressEventHandler( this, &ProjectForm::dataGridView_KeyPress ));

  e->Control->KeyDown -= EventKeyDown;
  e->Control->KeyPress -= EventKeyPress;

  e->Control->KeyDown += EventKeyDown;
  e->Control->KeyPress += EventKeyPress;
}

回答by Eyvind

Perhaps not as nice as Mladen Prajdic's answer above, but maybe a little easier, depending on your situation. You may override the ProcessCmdKey method of the form or the control itself, handle keystrokes there, and check for the current cell.

也许不如上面 Mladen Prajdic 的回答那么好,但可能会更容易一些,具体取决于您的情况。您可以覆盖窗体或控件本身的 ProcessCmdKey 方法,在那里处理击键,并检查当前单元格。

回答by Viesturs

I found a partial solution by listening to EditingControlShowing and adding key listener to each new editing control.

我通过侦听 EditingControlShowing 并将键侦听器添加到每个新的编辑控件中找到了部分解决方案。

This gives me access to most of the keys, but I still do not get arrow keys.

这使我可以访问大多数键,但我仍然没有获得箭头键。

I'll try out what Eren Aygunes suggested.

我会试试 Eren Aygunes 的建议。

回答by Mladen Prajdic

you have to override the DataGridViewCell/DataGridViewTextBoxCell/otherTypes and handle key* events in the derived class.

您必须覆盖 DataGridViewCell/DataGridViewTextBoxCell/otherTypes 并处理派生类中的 key* 事件。