KeyDown事件 - 如何轻松知道按下的键是数字键?

10

我目前正在处理DataGridView控件的KeyDown事件。其中一个列由计算出的值填充,如果用户希望,我希望用户能够覆盖单元格的值。

当用户按下数字键时,单元格进入编辑模式,允许用户覆盖值。 如果按键不是数字,则不会发生任何事情...

这个功能已经工作得很好了... 问题是我觉得代码很丑... 我似乎找不到一种简洁的方法来处理所有数字键,在一个条件语句中处理所有可能的数字键,所以我使用了switch case结构来处理所有可能的数字键,如下所示:

                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...]

当然,它可以工作,但一定有更好、更短的方法,对吧?

我在谷歌上只找到将 e.KeyCode 转换为 char 的方法,但是当使用数字键时,即使是数字值,它也会给出字母...

谢谢。

8个回答

19

试试

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

1
标记的答案是正确的,但是 TelerikGrid 不支持 KeyPress.. 这个可以工作! - Muds

17

如果您使用KeyPress事件,该事件的签名具有一个包含KeyChar成员的KeyPressEventArgs,该成员提供数字键的字符。 您可以对其进行TryParse,以确定它是否为数字。

private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
    int i;
    if (int.TryParse(e.KeyChar.ToString(), out i))
    {
        MessageBox.Show("Number");
    }
}

感谢Tim和Rawling。这就是我采用的解决方案。我还必须在KeyDown中处理DEL键事件...我更喜欢将所有内容保持在同一位置,但是这段代码看起来最好。也感谢其他所有人。 - Kharlos Dominguez

9

Sorcerer86pt的解决方案是最简单的,但当用户按下控制键(如退格键)时,它会出现问题。要解决这个问题,您可以使用以下代码片段:

void KeyPress(object sender, KeyPressEventArgs e)
{    
    if(!Char.IsNumber(e.KeyChar) && !Char.IsControl(e.KeyChar))
    {
        //The char is not a number or a control key
        //Handle the event so the key press is accepted
        e.Handled = true;
        //Get out of there - make it safe to add stuff after the if statement
        return;
    }
    //e.Handled remains false so the keypress is not accepted
}

如果您正在使用WPF,您可能会发现TextBox没有KeyPressed事件。要解决这个问题,我使用了以下代码。
void ValidateKeyPress(object sender, KeyEventArgs e)
{
    char keyPressed = WPFUtils.Interop.Keyboard.GetCharFromKey(e.Key);
    if (!Char.IsNumber(keyPressed) && !Char.IsControl(keyPressed))
    {
        //As above
        e.Handled = true;
        return;
    }
}

你可能会注意到这个奇怪的函数调用 WPFUtils.Interop.Keyboard.GetCharFromKey(e.Key),这是我收集的有用函数之一。你可以在这里找到它。


7

为什么要使用按键代码,当你可以使用这个:

void Control_KeyPress(object sender, KeyPressEventArgs e)
    {

        if (Char.IsDigit(e.KeyChar))
        {
            //do something
        }
        else
        {
            //do something else
        }
    }

这样做更加清晰易懂,即使微软决定改变所有枚举值,它仍然可以正常工作。


3
MSDN帮助页面上,他们在示例中使用了以下代码:
// 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)

@Rawling,@tanascius:谢谢,我确实考虑过这个问题,但我认为对枚举执行范围评估是一种不好的做法?我同意它来自MSDN使它相对安全,但毕竟,这不会是我们第一次看到来自MSDN的错误示例代码...有什么保证这些值始终是连续的吗?毕竟,我们有枚举类型,所以不能依赖底层值?通过执行这样的检查,我是否不是依赖于这些枚举值将彼此连续的事实?谢谢。 - Kharlos Dominguez
尽管这种做法可能不太好,但我希望微软在他们的文档中使用时会小心保持行为的一致性。如果你能切换到KeyPress事件而不是KeyDown,你就可以使用我提供的解决方案。 - Tim Coker
是的,如果有不这样做的理由,Tim的解决方案很好 - 而且也更明显你想要做什么。 - Rawling
@Kharlos:我理解你的问题,但是想一想如果它们改变了什么,会使你的代码崩溃。枚举类型可以更改,只要它们不改变 NumPad?D? 元素的顺序。而且我认为在 "NumPad8 之前定义 NumPad9 没有任何必要... - tanascius
是的,我同意你的观点,他们很可能不会这样做。这更多是一个修辞问题而不是现实世界中的问题,但如果可以的话,我也不会尝试打破最佳实践,即使在现实世界中它不太可能会造成任何问题。 - Kharlos Dominguez

2

更简洁的版本:

    private void KeyPress(object sender, KeyPressEventArgs e)
    {
        e.Handled = !Char.IsDigit(e.KeyChar); // only allow a user to enter numbers
    }

1
仅作为附注,这将禁止按下退格键以及除数字以外的任何键。 - Takarii

2

只需从按下的键(Key)中获取最后一个字符,如果按下的是数字,则该字符将为数字。 此方法适用于KeyDown事件,无需任何其他条件。

只需调用此静态方法并传入要检查的键(Key)即可。

public static bool IsNumber(Keys key)
{
  string num = key.ToString().Substring(key.ToString().Length - 1);
  Int64 i64;
  if (Int64.TryParse(num, out i64))
  {
    return true;               
  }
  return false;
}

0
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");
}

1
注意使用此方法时,它不考虑数字键盘值(NumPad0 = 96 = 'd')。 - Andy Braham

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接