views:

34

answers:

4

Hello,

I am currently handling the KeyDown event of a DataGridView control. One of the columns is filled by calculated values and I want the user to be able to override the cell value if they want.

When the user presses a numeric key, the cell goes into EditMode and allows the user to override the value. If the key is not numeric, nothing happens...

That is working pretty well... the problem is that I find the code for it ugly... I can't seem to find a neat way to handle all the numeric keys in a single condition, so I've made a switch case construct to deal with all the possible numeric keys, like this:

                switch (e.KeyCode)
                {
                    case Keys.D0:
                    case Keys.D1:
                    case Keys.D2:
                    case Keys.D3:
                    case Keys.D4:
                    case Keys.D5:
                    case Keys.D6:
                    case Keys.D7:
                    case Keys.D8:
                    case Keys.D9:
                    case Keys.Decimal:
                    case Keys.NumPad0:
                    case Keys.NumPad1:
                    case Keys.NumPad2:
                    case Keys.NumPad3:
                    case Keys.NumPad4:
                    case Keys.NumPad5:
                    case Keys.NumPad6:
                    case Keys.NumPad7:
                    case Keys.NumPad8:
                    case Keys.NumPad9:

                         [code to make the cell go to editMode, etc...]

Sure, it works, but there has to be a better and shorter way, right?

All I could find using Google is converting e.KeyCode to a char, but when using numeric keys, it goes gives letters even for the numeric values...

Thanks.

A: 

On the msdn help page they use this code in their example:

// 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)
tanascius
@Rawling, @tanascius: thanks, I did think about that but I thought that it was a bad practice to perform range evaluations against enumerations?I agree that the fact that it comes from MSDN makes it relatively safe, but after all, it wouldn't be the first time we would see bad example code from MSDN...Is there anything that guarantees that the values will always be contiguous? After all, we have enumerations so to not rely on the underlying values? By performing such a check, am I not relying on the fact that these enumerations values will be contiguous to each other? Thanks.
Kharlos Dominguez
As bad as a practice as that may be, I would hope that since Microsoft is using that in their docs, they would be careful to keep the behavior consistent. If you can switch to the KeyPress event instead of KeyDown, you can use the solution I provided.
Tim Coker
Yeah, if there's a reason not to do that, Tim's solution is good - and makes it a lot more obvious what you're trying to do, too.
Rawling
@Kharlos: I understand the issues you have, but think about what they would have to change to make your code break. The enum can change without any problem as long as they do not change the order of the *NumPad?* and *D?* elements. And I think that there is no reason to define *NumPad9* before *"NumPad8* ...
tanascius
Yeah, I agree with you that is very unlikely that they would do that. It is more a rhetorical issue than a real-world one, but if I can, I might as well not try to break a best practice, even if it is unlikely it would pose any problem in the real-world.
Kharlos Dominguez
+3  A: 

Try

if ((e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9) ||
    (e.KeyCode >= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9) ||
    e.KeyCode == Keys.Decimal)
{
    // Edit mode
}
Rawling
+4  A: 

If you use the KeyPress event, the event signature has a KeyPressEventArgs with a KeyChar member that gives you the character for the numberpad keys. You can do a TryParse on that to figure out if its a number or not.

private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
    int i;
    if (int.TryParse(e.KeyChar.ToString(), out i))
    {
        MessageBox.Show("Number");
    }
}
Tim Coker
Or even e.KeyChar.IsDigit()?
Rawling
Thanks Tim and Rawling. That's the solution I went with. I also have to handle a DEL key event in KeyDown... I would have preferred to keep it all at the same spot, but this code looks by far the nicest. Thanks everyone else as well.
Kharlos Dominguez
A: 

void dataGridView1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e) { // Used this to find they key values. //label1.Text += e.KeyValue;

        // Check if key is numeric value.
        if((e.KeyValue >= 48 && e.KeyValue <= 57) || (e.KeyValue >= 97 && e.KeyValue <= 105))
            System.Console.WriteLine("Pressed key is numeric");
    }
MrFox