Reputation: 1691
I need to receive the key press events during cell editing in DataGridView
control.
From what I have found on the net the DataGridView
is designed to pass all key events from DataGridView
to the cell editing control and you cannot get these events easily.
I found this piece of code that traps those events for DataGrid
control, but that does not work for DataGridView
.
Upvotes: 7
Views: 21793
Reputation:
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.
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;
}
Upvotes: 2
Reputation: 1691
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.
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;
}
Upvotes: 2
Reputation: 1691
I found a partial solution by listening to EditingControlShowing and adding key listener to each new editing control.
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.
Upvotes: 0
Reputation: 997
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());
}
}
Upvotes: 2
Reputation: 5271
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.
Upvotes: 1
Reputation: 15685
you have to override the DataGridViewCell/DataGridViewTextBoxCell/otherTypes and handle key* events in the derived class.
Upvotes: 0