views:

48

answers:

2

Hello,

On a WinForms application that I am writing in C#, I have a DataGridViewTextBoxColumn with cells holding integer values that I would like the users to be able to increment or decrement using the + and - keys from their keyboards.

I've handled the KeyDown event as it is what I use usually to handle Delete keys, etc, but it isn't working for Plus and Minus keys as pressing them causes the Cell to go in Edit-mode, and the KeyDown event is never fired for those keys as a result. Same for the KeyPress event

Actually, it is fired if I set the cells to readonly, but I am not happy with this solution as it would force me to set the property from true to false in several areas of my code and could quickly become messy.

What would please be the best way to achieve this?

Thanks.

+2  A: 

You need to trap the keystroke before they get to the datagrid.

This looks suprisingly close to what you're trying to do: http://support.microsoft.com/kb/320584

Dave Swersky
Alright, thanks. It is working. Actually, a simpler solution than what is shown in the KB is to set the KeyPreview property of the form to true and then handle the KeyDown event of the form.While it works, it has several drawbacks: some logic of the DataGridView is in form's related events rather than being in the DataGridView's events. As the cell still goes into edit-mode even with this solution, I had to keep track of whether the keys were pressed and in the correct columns in a bool flag, and cancel the CellBeginEdit event if the flag is true in order to prevent it to go in edit-mode.
Kharlos Dominguez
Aside the fact that it is not as elegant as I would have wanted, this works quite well, so thanks a lot. I'll let this open for a while just in case someone else may have other suggestions.
Kharlos Dominguez
+1  A: 

Wow, that KB article is pretty bad. That should be done by overriding IsInputKey().

I don't care much for DGV, it is a bugger to customize. But you can probably whack this into some kind of shape:

using System;
using System.Windows.Forms;

class MyDgv : DataGridView {
    public event EventHandler Increment;
    public event EventHandler Decrement;

    protected override void OnKeyDown(KeyEventArgs e) {
        bool used = false;
        if (this.EditingControl == null) {
            if (e.KeyData == Keys.Oemplus) {
                if (Increment != null) { Increment(this, EventArgs.Empty); used = true; }
            }
            else if (e.KeyData == Keys.OemMinus) {
                if (Decrement != null) { Decrement(this, EventArgs.Empty); used = true; }
            }
        }
        if (used) e.SuppressKeyPress = e.Handled = true;
        else base.OnKeyDown(e);
    }
}
Hans Passant
Thanks, that is elegant. I tried it and it works if I cancel the CellBeginEdit event. The problem, is that the OnKeyDown event of the DataGridView triggers after the CellBeginEdit event, so I have no way to determine which key was pressed by the user in order to cancel the event or not. Any idea? Also, you say that the DGV is a pain to customize: I thought it was very thorough at first, but I agree that I'm quickly running into its limitations? Any 3rd party suggestions? All the ones I tried seem awfully skinned/themed and I liked the DGV's style as it blends well with other WinForms controls.
Kharlos Dominguez
This is *exactly* what I meant, it's a pain. Do set e.SuppressKeyPress and e.Handled to true if you use the keystroke, I forgot to include that. Post updated.
Hans Passant
Thanks, I've tried your new code but the problem is that the Increment and Decrement event handlers do not trigger if the cell can be modified by the user. If I set them to read-only, the events do occur, but in my case, they need to be modifiable.It looks as if the cell going to editing mode occur before the OnKeyDown method, and prevent it from ever running.In my case, the cells should be modified by the users.The method used in my comment below Dave's answer work, because the form events trigger before any of the DGVs, but it is not really elegant as I said. Any way to make yours work?
Kharlos Dominguez