【问题标题】:How to create a numeric textbox in Silverlight?如何在 Silverlight 中创建数字文本框?
【发布时间】:2008-11-06 10:19:39
【问题描述】:

正如标题所说的那样。 我看过从 TextBox 继承,但唯一合理的覆盖是“OnKeyDown”,但这只是给了我一个来自 Key 枚举的键(无法使用 Char.IsNumeric())。

【问题讨论】:

    标签: c# .net silverlight textbox silverlight-2.0


    【解决方案1】:

    我接受了 Nidhal 的建议答案并对其进行了一些编辑,以处理数字上方字符的移位大小写(即!@#$%^&*()),因为该解决方案仍将允许文本框中的这些字符。

    private void NumClient_KeyDown(object sender, KeyEventArgs e)
    {       
        // Handle Shift case
        if (Keyboard.Modifiers == ModifierKeys.Shift)
        {
           e.Handled = true;
        }
    
        // Handle all other cases
        if (!e.Handled && (e.Key < Key.D0 || e.Key > Key.D9))
        {
            if (e.Key < Key.NumPad0 || e.Key > Key.NumPad9)
            {
                if (e.Key != Key.Back)
                {
                    e.Handled = true;
                }
            }
        }           
    }
    

    【讨论】:

    • 这也吞下了 TAB 和 shift-Tab 键。
    • 你会如何在 MVVM 中做到这一点?
    【解决方案2】:

    访问http://www.dataartist.net/blog/post/Silverlight-Behavior-Modifications-13-NumericOnlyBehavior.aspx 或使用如下文本框行为

      using System;
      using System.Windows;
      using System.Windows.Controls;
      using System.Windows.Input;
      using System.Windows.Interactivity;
    
      namespace DataArtist
      {
    public class NumericOnly : Behavior<TextBox>
    {
        private string Text { get; set; }
        private bool shiftKey;
        public bool StripOnExit { get; set; }
    
        public NumericOnly()
        {
            StripOnExit = false;
        }
    
        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.KeyDown += KeyDown;
            AssociatedObject.KeyUp += KeyUp;
            AssociatedObject.GotFocus += GotFocus;
            AssociatedObject.LostFocus += LostFocus;
        }
    
        void KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Shift)
            {
                shiftKey = false;
            }
        }
    
        void KeyDown(object sender, KeyEventArgs e)
        {
            if (StripOnExit != false || e.Key == Key.Tab || e.Key == Key.Enter)
            {
                return;
            }
    
            if (e.Key == Key.Shift)
            {
                shiftKey = true;
            }
            else
            {
                if (IsNumericKey(e.Key) == false)
                {
                    e.Handled = true;
                }
            }
        }
    
        void GotFocus(object sender, RoutedEventArgs e)
        {
            Text = AssociatedObject.Text;
        }
    
        private void LostFocus(object sender, RoutedEventArgs e)
        {
            if (AssociatedObject.Text == Text)
            {
                return;
            }
    
            string content = string.Empty;
    
            foreach (var c in AssociatedObject.Text)
            {
                if (Char.IsNumber(c) == true)
                {
                    content += c;
                }
            }
    
            AssociatedObject.Text = content;
        }
    
        public bool IsNumericKey(Key key)
        {
            if (shiftKey == true)
            {
                return false;
            }
    
            string code = key.ToString().Replace("NumPad", "D");
    
            if (code[0] == 'D' && code.Length > 1)
            {
                return (Char.IsNumber(code[1]));
            }
    
            return false;
        }
    
        protected override void OnDetaching()
        {
            base.OnDetaching();
            AssociatedObject.KeyDown -= KeyDown;
            AssociatedObject.LostFocus -= LostFocus;
            AssociatedObject.GotFocus -= GotFocus;
        }
    }   
        }
    

    【讨论】:

    • 行为绝对是要走的路。它也比附加属性更容易清除。 (连接到 KeyUp 和 KeyDown 处理程序的附加属性很有可能创建 GC 根并防止垃圾收集。可以修改行为,以便在 Loaded 事件中添加所有事件处理程序,然后在 Unloaded 事件中取消挂钩。)
    【解决方案3】:
    private void Numclient_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key < Key.D0 || e.Key > Key.D9)
        {
            if (e.Key < Key.NumPad0 || e.Key > Key.NumPad9)
            {
                if (e.Key != Key.Back && e.Key != Key.Shift)
                {
                    e.Handled = true;
                }
            }
        }
    }
    

    【讨论】:

    【解决方案4】:

    查看工具包中的 NumericUpDown http://codeplex.com/Silverlight,也许您可​​以使用它或查看源代码来实现您自己的数字文本框。

    【讨论】:

    • NumericUpDown 只有一个问题。例如,你有值 999,你使用退格键清除输入,然后你失去焦点,它再次将 999 设置回来,而不是设置为 0。
    • 为什么你认为这是一个问题? =))
    【解决方案5】:

    看看这个,它在文本框上使用了一个附加属性。我正在使用它,它确实有效。 http://weblogs.asp.net/manishdalal/archive/2008/09/24/prevention-the-first-line-of-defense-with-attach-property-pixie-dust.aspx

    【讨论】:

    • 你的链接好像失效了
    【解决方案6】:
        private void TextBox_KeyDown(object sender, KeyEventArgs e)
        {
            bool isDigit = e.Key >= Key.D0 && e.Key < Key.D9 || e.Key == Key.NumPad0 || e.Key == Key.NumPad1 || e.Key == Key.NumPad2 || e.Key == Key.NumPad3 || e.Key == Key.NumPad4 || e.Key == Key.NumPad5 || e.Key == Key.NumPad6 ||
            e.Key == Key.NumPad7 || e.Key == Key.NumPad8 || e.Key == Key.NumPad9 ||e.Key == Key.Back || e.Key == Key.Delete || e.Key == Key.Left || e.Key == Key.Right;
    
            if (isDigit) { }
            else
                e.Handled = true; 
        }
    

    【讨论】:

      【解决方案7】:
      private void txtbox_KeyDown(object sender, KeyEventArgs e)
      {
          if (e.Key == Key.D0 || e.Key == Key.D1 || e.Key == Key.D2 || e.Key == Key.D3 || e.Key == Key.D4 || e.Key == Key.D5 || e.Key == Key.D6 || e.Key == Key.D7 || e.Key == Key.D8 || e.Key == Key.D9 || e.Key == Key.NumPad0 || e.Key == Key.NumPad1 || e.Key == Key.NumPad2 || e.Key == Key.NumPad3 || e.Key == Key.NumPad4 || e.Key == Key.NumPad5 || e.Key == Key.NumPad6 || e.Key == Key.NumPad7 || e.Key == Key.NumPad8 || e.Key == Key.NumPad9)
              e.Handled = false;
          else
              e.Handled = true;
      }
      

      【讨论】:

        【解决方案8】:

        我知道它已被回答,但我发现没有合适的解决方案来处理所有特殊情况,这里的大多数答案都会吞下一些重要的键,如 Home、End、Tab、Shift+ 任何东西,..等等。

        所以,我开发了自己的实现,因为它可能对某人有所帮助!

        public class IntegerTextBox : TextBox
            {
                /// <summary>
                /// To be raised whenever integer value changed
                /// </summary>
                public event EventHandler ValueChanged;
        
                /// <summary>
                /// To restore if the user entered invalid characters
                /// </summary>
                private int lastSavedValue = 0;
        
                private int lastSelectionStart = 0;
                private int lastSelectionLength = 0;
        
        
                public int IntegerValue
                {
                    get
                    {
                        //the default value is 0 if there is no text in the textbox
                        int value = 0;
                        int.TryParse(Text, out value);
                        return value;
                    }
                    set
                    {
                        if (this.Text.Trim() != value.ToString())
                        {
                            Text = value.ToString();
                        }
                    }
                }
        
                public IntegerTextBox()
                    : base()
                {
                    this.LostFocus += (sender, e) =>
                        {
                            //if the user clears the text the text box and leaves it, set it to default value
                            if (string.IsNullOrWhiteSpace(this.Text))
                                IntegerValue = 0;
                        };
                    this.Loaded += (sender, e) =>
                        {
                            //populate the textbox with Initial IntegerValue (default = 0)
                            this.Text = this.IntegerValue.ToString();
                        };
        
                    this.TextChanged += (sender, e) =>
                        {
                            int newValue = 0;
                            if (int.TryParse(this.Text, out newValue)) //this will handle most cases like number exceeds the int max limits, negative numbers, ...etc.
                            {
                                if (string.IsNullOrWhiteSpace(Text) || lastSavedValue != newValue)
                                {
                                    lastSavedValue = newValue;
                                    //raise the event
                                    EventHandler handler = ValueChanged;
                                    if (handler != null)
                                        handler(this, EventArgs.Empty);
        
                                }
                            }
                            else 
                            {
                                //restore previous number
                                this.Text = lastSavedValue.ToString();
                                //restore selected text
                                this.SelectionStart = lastSelectionStart;
                                this.SelectionLength = lastSelectionLength;
                            }
                        };
        
                    this.KeyDown += (sender, e) =>
                        {
                            //before every key press, save selection start and length to handle overwriting selected numbers
                            lastSelectionStart = this.SelectionStart;
                            lastSelectionLength = this.SelectionLength;
                        };
                }
            } 
        

        上面的代码有一个缺点,TextChanged 事件会被频繁触发,但是既然我们需要一个integer 文本框,那么我们可以依赖ValueChanged 来代替!

        【讨论】:

          【解决方案9】:

          有效:

          static bool AltGrIsPressed;
          
          void Numclient_KeyUp(object sender, KeyEventArgs e)
          {
              if (e.Key == Key.Alt)
              {
                  AltGrIsPressed = false;
              }
          }
          
          void Numclient_KeyDown(object sender, KeyEventArgs e)
          {
              if (e.Key == Key.Alt)
              {
                  AltGrIsPressed = true;
              }
          
              if (Keyboard.Modifiers == ModifierKeys.Shift || AltGrIsPressed == true)
              {
                  e.Handled = true;
              }
          
              if (e.Handled == false && (e.Key < Key.D0 || e.Key > Key.D9))
              {
                  if (e.Key < Key.NumPad0 || e.Key > Key.NumPad9)
                  {
                      if (e.Key != Key.Back)
                      {
                          e.Handled = true;
                      }
                  }
              }       
          }
          

          【讨论】:

            【解决方案10】:

            扩展普通的 Silverlight 文本框控件。在扩展的 TextBox 类中添加此代码:

            string nums = "1234567890";
            string lastText = "";
            int lastSelStart = 0;
            
            protected override void TextChanged(object sender, TextChangedEventArgs e)
            {
                if(!nums.Contains(this.Text.Substring(this.Text.Length -1)))
                {
                     this.Text = lastText;
                     this.SelectionStart = lastSelStart;
                     return;
                }
            
                lastText = this.Text;
                lastSelStart = this.SelectionStart;
            
            }
            

            【讨论】:

              【解决方案11】:

              为什么每个人都不努力处理所有问题?

              这里(这是完美的):

              <TextBox KeyDown="TextBox_KeyDown" />
              
              private void TextBox_KeyDown(object sender, KeyEventArgs e)
              {
                  var _Letter = string.Empty;
                  switch (e.Key)
                  {
                      case Key.A: _Letter = "A"; break;
                      case Key.Add: _Letter = "+"; break;
                      case Key.Alt: break;
                      case Key.B: _Letter = "B"; break;
                      case Key.Back: break;
                      case Key.C: _Letter = "C"; break;
                      case Key.CapsLock: break;
                      case Key.Ctrl: break;
                      case Key.D: _Letter = "D"; break;
                      case Key.D0: _Letter = "0"; break;
                      case Key.D1: _Letter = "1"; break;
                      case Key.D2: _Letter = "2"; break;
                      case Key.D3: _Letter = "3"; break;
                      case Key.D4: _Letter = "4"; break;
                      case Key.D5: _Letter = "5"; break;
                      case Key.D6: _Letter = "6"; break;
                      case Key.D7: _Letter = "7"; break;
                      case Key.D8: _Letter = "8"; break;
                      case Key.D9: _Letter = "9"; break;
                      case Key.Decimal: _Letter = "."; break;
                      case Key.Delete: break;
                      case Key.Divide: _Letter = "/"; break;
                      case Key.Down: break;
                      case Key.E: _Letter = "E"; break;
                      case Key.End: break;
                      case Key.Enter: break;
                      case Key.Escape: break;
                      case Key.F: _Letter = "F"; break;
                      case Key.F1: break;
                      case Key.F10: break;
                      case Key.F11: break;
                      case Key.F12: break;
                      case Key.F2: break;
                      case Key.F3: break;
                      case Key.F4: break;
                      case Key.F5: break;
                      case Key.F6: break;
                      case Key.F7: break;
                      case Key.F8: break;
                      case Key.F9: break;
                      case Key.G: _Letter = "G"; break;
                      case Key.H: _Letter = "H"; break;
                      case Key.Home: break;
                      case Key.I: _Letter = "I"; break;
                      case Key.Insert: break;
                      case Key.J: _Letter = "J"; break;
                      case Key.K: _Letter = "K"; break;
                      case Key.L: _Letter = "L"; break;
                      case Key.Left: break;
                      case Key.M: _Letter = "M"; break;
                      case Key.Multiply: _Letter = "*"; break;
                      case Key.N: _Letter = "N"; break;
                      case Key.None: break;
                      case Key.NumPad0: _Letter = "0"; break;
                      case Key.NumPad1: _Letter = "1"; break;
                      case Key.NumPad2: _Letter = "2"; break;
                      case Key.NumPad3: _Letter = "3"; break;
                      case Key.NumPad4: _Letter = "4"; break;
                      case Key.NumPad5: _Letter = "5"; break;
                      case Key.NumPad6: _Letter = "6"; break;
                      case Key.NumPad7: _Letter = "7"; break;
                      case Key.NumPad8: _Letter = "8"; break;
                      case Key.NumPad9: _Letter = "9"; break;
                      case Key.O: _Letter = "O"; break;
                      case Key.P: _Letter = "P"; break;
                      case Key.PageDown: break;
                      case Key.PageUp: break;
                      case Key.Q: _Letter = "Q"; break;
                      case Key.R: _Letter = "R"; break;
                      case Key.Right: break;
                      case Key.S: _Letter = "S"; break;
                      case Key.Shift: break;
                      case Key.Space: _Letter = " "; break;
                      case Key.Subtract: _Letter = "-"; break;
                      case Key.T: _Letter = "T"; break;
                      case Key.Tab: break;
                      case Key.U: _Letter = "U"; break;
                      case Key.Unknown: break;
                      case Key.Up: break;
                      case Key.V: _Letter = "V"; break;
                      case Key.W: _Letter = "W"; break;
                      case Key.X: _Letter = "X"; break;
                      case Key.Y: _Letter = "Y"; break;
                      case Key.Z: _Letter = "Z"; break;
                      default: break;
                  }
                  var _Text = (sender as TextBox).Text + _Letter;
                  double _Double;
                  e.Handled = !double.TryParse(_Text, out _Double);
              }
              

              }

              【讨论】:

              • Key.D0 到 Key.D9 不代表 AZERTY 上的数字,例如(仅与 shift 结合使用)。这只是修复此代码的开始。如此完美……
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-02-15
              • 1970-01-01
              • 2017-04-06
              • 1970-01-01
              相关资源
              最近更新 更多