Silverlight限制TextBox只能输入整数或者小数

Silverlight功能还不完善,简化了一下WebForm或者WinForm的同类方法。
大气象
private void txtRoomNum_KeyDown(object sender, KeyEventArgs e)
{
    TextBox txt 
= sender as TextBox;
    
//屏蔽非法按键,只能输入整数
    if ((e.Key >= Key.NumPad0 && e.Key <= Key.NumPad9))
    {
        e.Handled 
= false;
    }
    
else
    {
        e.Handled 
= true;
    }
}

private void txtRoomArea_KeyDown(object sender, KeyEventArgs e)
{
    TextBox txt 
= sender as TextBox;
    
//屏蔽非法按键,只能输入小数
    if ((e.Key >= Key.NumPad0 && e.Key <= Key.NumPad9) || e.Key == Key.Decimal)
    {
        
if (txt.Text.Contains("."&& e.Key == Key.Decimal)
        {
            e.Handled 
= true;
            
return;
        }
        e.Handled 
= false;
    }
    
else
    {
        e.Handled 
= true;
    }

}

 

 

参考一:
以下实现TextBox只能输入小数并且屏蔽中文输入和非法粘贴:
说明:以下实现均在Framework 3.0平台下

为TextBox加两个事件:TextChanged和KeyDown事件,具体如下:
KeyDown事件:

 1private void TextBox_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
 2        {
 3            TextBox txt = sender as TextBox;
 4
 5             //屏蔽非法按键
 6            if ((e.Key >= Key.NumPad0 && e.Key <= Key.NumPad9) || e.Key == Key.Decimal)
 7            {
 8                if (txt.Text.Contains("."&& e.Key == Key.Decimal)
 9                {
10                    e.Handled = true;
11                    return;
12                }

13                e.Handled = false;
14            }

15            else if (((e.Key >= Key.D0 && e.Key <= Key.D9) || e.Key == Key.OemPeriod) && e.KeyboardDevice.Modifiers != ModifierKeys.Shift)
16            {
17                if (txt.Text.Contains("."&& e.Key == Key.OemPeriod)
18                {
19                    e.Handled = true;
20                    return;
21                }

22                e.Handled = false;
23            }

24            else
25            {
26                e.Handled = true;
27            }

28        }

29
30
TextChanged事件
 1private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
 2        {
 3            //屏蔽中文输入和粘贴输入
 4            TextBox textBox = sender as TextBox;
 5            TextChange[] change = new TextChange[e.Changes.Count];
 6            e.Changes.CopyTo(change, 0);
 7
 8            int offset = change[0].Offset;
 9            if (change[0].AddedLength > 0)
10            {
11                double num = 0;
12                if (!Double.TryParse(textBox.Text, out num))
13                {
14                    textBox.Text = textBox.Text.Remove(offset, change[0].AddedLength);
15                    textBox.Select(offset, 0);
16                }

17            }

18        }

19
20

值得注意的是TextChange类,是Framework 3.0SP1和3.5中新增的,3.0本身是没有的

参考二:C#Winform下用正则表达式限制TextBox只能输入数字
昨天,在网上特别是园子里搜了下如何在Winform下限制TextBox只能输入数字的功能。可是结果基本上都是在web的环境下用正则表达式实现的,而在Winform的平台下,好像没有发现。   就自己循着思路实现了下。

首先,先定义一个string,用来表示数字的正则表达式:
 private string pattern = @"^[0-9]*$";

然后再定义一个
string,用来记录TextBox原来的内容,以便在输入非数字的时候,文本框的内容可以恢复到原来的值(我不知道TextBox怎么恢复到上一次的内容,只能采用这个笨办法了):

private string param1 = null;


接着,我们就可以在textBox的TextChanged事件中判断输入的是否是数字,如果是数字,那么就把文本框的内容保存在param1中;如果不是数字,那么取消这次输入,即重新设置文本框的内容为param1:

        private void textBoxParam1_TextChanged(object sender, EventArgs e)
        
{
            Match m 
= Regex.Match(this.textBoxParam1.Text, pattern);   // 匹配正则表达式

            
if (!m.Success)   // 输入的不是数字
            {
                
this.textBoxParam1.Text = param1;   // textBox内容不变

                
// 将光标定位到文本框的最后
                this.textBoxParam1.SelectionStart = this.textBoxParam1.Text.Length;
            }

            
else   // 输入的是数字
            {
                param1 
= this.textBoxParam1.Text;   // 将现在textBox的值保存下来
            }

        }


这样,就基本上实现了用正则表达式限制TextBox的输入数字了。
其他的现在也是类似,只要设定比较的正则表达式的内容即可。

 

参考三:Silverlight开发中的疑难杂症-控件设计篇-如何实现一个NumericBox(上)

在最近的Silverlight开发中,发现一个需求,需要一个只能够输入数字,并且能够对小数点后的位数进行控制并填充的控件,原有的TextBox并不能实现这一个功能,于是就决定自己实现一个,要包含的具体的功能如下:

只能输入0-9的数字和至多一个小数点;

能够屏蔽通过非正常途径的不正确输入(输入法,粘贴等);

能够控制小数点后的最大位数,超出位数则无法继续输入;

能够选择当小数点数位数不足时是否补0

去除开头部分多余的0(为方便处理,当在开头部分输入0时,自动在其后添加一个小数点);

由于只能输入一个小数点,当在已有的小数点前再次按下小数点,能够跳过小数点;

在实现前参考了许多网上的相关资料,虽然没有找到具体的实现代码,但是还是得到了很多有用的思路,最终决定将上述功能分成两个部分来实现:其中控制只能输入数字的部分作为一个通用的TextBoxFilterBehavior进行设计;而格式化的部分则在NumericBox内部实现,下面首先介绍TextBoxFilterBehavior的实现。

在实现之前,首先查看了TextBox的相关事件,发现Silverlight中的事件比WPF来说有了很大的减少,没得选择,可用的事件只有KeyDownTextChanged。这里使用KeyDown事件来处理按键产生的输入,TextChanged事件来处理通过其它方式进行的输入(其实完全可以都在TextChanged事件中进行处理,我也想不通为什么自己选择分开进行~)。

由于要做成一个通用的TextBox筛选行为,所以这里添加了一个筛选类型的枚举选项TextBoxFilterOptions,里面暂时只有数字、小数点跟字母,留待以后扩充,实现代码如下:

TextBoxFilterOptions
 1 /// <summary>
 2     /// TextBox筛选选项
 3     /// </summary>
 4     [Flags]
 5     public enum TextBoxFilterOptions
 6     {
 7         /// <summary>
 8         /// 不采用任何筛选
 9         /// </summary>
10         None = 0,
11         /// <summary>
12         /// 数字类型不参与筛选
13         /// </summary>
14         Numeric = 1,
15         /// <summary>
16         /// 字母类型不参与筛选
17         /// </summary>
18         Character = 2,
19         /// <summary>
20         /// 小数点不参与筛选
21         /// </summary>
22         Dot = 4,
23         /// <summary>
24         /// 其它类型不参与筛选
25         /// </summary>
26         Other = 8
27     }
28 
29     /// <summary>
30     /// TextBox筛选选项枚举扩展方法
31     /// </summary>
32     public static class TextBoxFilterOptionsExtension
33     {
34         /// <summary>
35         /// 在全部的选项中是否包含指定的选项
36         /// </summary>
37         /// <param name="allOptions">所有的选项</param>
38         /// <param name="option">指定的选项</param>
39         /// <returns></returns>
40         public static bool ContainsOption(this TextBoxFilterOptions allOptions, TextBoxFilterOptions option)
41         {
42             return (allOptions & option) == option;
43         }
44     }
45 

其中ContainsOption方法是一个提供了方便的枚举运算的扩展方法。

       另外还增加了一个键盘操作的帮助类KeyboardHelper,在实现时发现Silverlight中的按键比WPF中少了很多,甚至连主键盘上的小数点键(句号)都无法识别,这里使用了一个平台相关的keycode进行判别,如果有更好的方法请给我留言。代码如下:

KeyboardHelper
  1 /// <summary>
  2     /// 键盘操作帮助类
  3     /// </summary>
  4     public class KeyboardHelper
  5     {
  6         /// <summary>
  7         /// 键盘上的句号键
  8         /// </summary>
  9         public const int OemPeriod = 190;
 10 
 11         #region Fileds
 12 
 13         /// <summary>
 14         /// 控制键
 15         /// </summary>
 16         private static readonly List<Key> _controlKeys = new List<Key>
 17                                                             {
 18                                                                 Key.Back,
 19                                                                 Key.CapsLock,
 20                                                                 Key.Ctrl,
 21                                                                 Key.Down,
 22                                                                 Key.End,
 23                                                                 Key.Enter,
 24                                                                 Key.Escape,
 25                                                                 Key.Home,
 26                                                                 Key.Insert,
 27                                                                 Key.Left,
 28                                                                 Key.PageDown,
 29                                                                 Key.PageUp,
 30                                                                 Key.Right,
 31                                                                 Key.Shift,
 32                                                                 Key.Tab,
 33                                                                 Key.Up
 34                                                             };
 35 
 36         #endregion
 37 
 38         /// <summary>
 39         /// 是否是数字键
 40         /// </summary>
 41         /// <param name="key">按键</param>
 42         /// <returns></returns>
 43         public static bool IsDigit(Key key)
 44         {
 45             bool shiftKey = (Keyboard.Modifiers & ModifierKeys.Shift) != 0;
 46             bool retVal;
 47             //按住shift键后,数字键并不是数字键
 48             if (key >= Key.D0 && key <= Key.D9 && !shiftKey)
 49             {
 50                 retVal = true;
 51             }
 52             else
 53             {
 54                 retVal = key >= Key.NumPad0 && key <= Key.NumPad9;
 55             }
 56             return retVal;
 57         }
 58 
 59         /// <summary>
 60         /// 是否是控制键
 61         /// </summary>
 62         /// <param name="key">按键</param>
 63         /// <returns></returns>
 64         public static bool IsControlKeys(Key key)
 65         {
 66             return _controlKeys.Contains(key);
 67         }
 68 
 69         /// <summary>
 70         /// 是否是小数点
 71         /// Silverlight中无法识别问号左边的那个小数点键
 72         /// 只能识别小键盘中的小数点
 73         /// </summary>
 74         /// <param name="key">按键</param>
 75         /// <returns></returns>
 76         public static bool IsDot(Key key)
 77         {
 78             return key == Key.Decimal;
 79         }
 80 
 81         /// <summary>
 82         /// 是否是小数点
 83         /// </summary>
 84         /// <param name="key">按键</param>
 85         /// <param name="keyCode">平台相关的按键代码</param>
 86         /// <returns></returns>
 87         public static bool IsDot(Key key, int keyCode)
 88         {
 89             return IsDot(key) || (key == Key.Unknown && keyCode == OemPeriod); 
 90         }
 91 
 92         /// <summary>
 93         /// 是否是字母键
 94         /// </summary>
 95         /// <param name="key">按键</param>
 96         /// <returns></returns>
 97         public static bool IsCharacter(Key key)
 98         {
 99             return key >= Key.A && key <= Key.Z;
100         }
101     }
102 

最后是TextBoxFilterBehavior的实现,关于Behavior的相关概念,大家可以参见Blend的帮助文档以及MSDN的相关文章,园子里也有很多大牛对它进行了详细的阐述,我就不深入讲解了。在这里,我们首先添加了一个TextBoxFilterOptions类型的依赖属性,用来设置过滤的选项,如下:

Dependency Properties
 1 #region Dependency Properties
 2 
 3         /// <summary>
 4         /// TextBox筛选选项,这里选择的为过滤后剩下的按键
 5         /// 控制键不参与筛选,可以多选组合
 6         /// </summary>
 7         public TextBoxFilterOptions TextBoxFilterOptions
 8         {
 9             get { return (TextBoxFilterOptions)GetValue(TextBoxFilterOptionsProperty); }
10             set { SetValue(TextBoxFilterOptionsProperty, value); }
11         }
12 
13         // Using a DependencyProperty as the backing store for TextBoxFilterOptions.  This enables animation, styling, binding, etc...
14         public static readonly DependencyProperty TextBoxFilterOptionsProperty =
15             DependencyProperty.Register("TextBoxFilterOptions"typeof(TextBoxFilterOptions), typeof(TextBoxFilterBehavior), new PropertyMetadata(TextBoxFilterOptions.None));
16 
17         #endregion
18 

然后注册了关联的TextBox控件的KeyDownTextChanged事件,在里面对输入的文本进行了验证,如果没有通过验证,则将文本充值回上次正确的文本。由于在TextChanged事件中并没有WPF里面的TextChange数组,所以无法拿到本次变更的文本,只能选择处理完整的Text完整的代码如下:

TextBoxFilterBehavior
  1 /// <summary>
  2     /// TextBox筛选行为,过滤不需要的按键
  3     /// </summary>
  4     public class TextBoxFilterBehavior : Behavior<TextBox>
  5     {
  6         private string _prevText = string.Empty;
  7 
  8         public TextBoxFilterBehavior()
  9         {
 10         }
 11 
 12         #region Dependency Properties
 13 
 14         /// <summary>
 15         /// TextBox筛选选项,这里选择的为过滤后剩下的按键
 16         /// 控制键不参与筛选,可以多选组合
 17         /// </summary>
 18         public TextBoxFilterOptions TextBoxFilterOptions
 19         {
 20             get { return (TextBoxFilterOptions)GetValue(TextBoxFilterOptionsProperty); }
 21             set { SetValue(TextBoxFilterOptionsProperty, value); }
 22         }
 23 
 24         // Using a DependencyProperty as the backing store for TextBoxFilterOptions.  This enables animation, styling, binding, etc...
 25         public static readonly DependencyProperty TextBoxFilterOptionsProperty =
 26             DependencyProperty.Register("TextBoxFilterOptions"typeof(TextBoxFilterOptions), typeof(TextBoxFilterBehavior), new PropertyMetadata(TextBoxFilterOptions.None));
 27 
 28         #endregion
 29 
 30         protected override void OnAttached()
 31         {
 32             base.OnAttached();
 33 
 34             this.AssociatedObject.KeyDown += new KeyEventHandler(AssociatedObject_KeyDown);
 35             this.AssociatedObject.TextChanged += new TextChangedEventHandler(AssociatedObject_TextChanged);
 36         }
 37 
 38         protected override void OnDetaching()
 39         {
 40             base.OnDetaching();
 41 
 42             this.AssociatedObject.KeyDown -= new KeyEventHandler(AssociatedObject_KeyDown);
 43             this.AssociatedObject.TextChanged -= new TextChangedEventHandler(AssociatedObject_TextChanged);
 44         }
 45 
 46         #region Events
 47 
 48         /// <summary>
 49         /// 处理通过其它手段进行的输入
 50         /// </summary>
 51         /// <param name="sender"></param>
 52         /// <param name="e"></param>
 53         void AssociatedObject_TextChanged(object sender, TextChangedEventArgs e)
 54         {
 55             //如果符合规则,就保存下来
 56             if (IsValidText(this.AssociatedObject.Text))
 57             {
 58                 _prevText = this.AssociatedObject.Text;
 59             }
 60             //如果不符合规则,就恢复为之前保存的值
 61             else 
 62             {
 63                 int selectIndex = this.AssociatedObject.SelectionStart - (this.AssociatedObject.Text.Length - _prevText.Length);                
 64                 this.AssociatedObject.Text = _prevText;
 65                 this.AssociatedObject.SelectionStart = selectIndex;
 66             }
 67 
 68         }
 69 
 70         /// <summary>
 71         /// 处理按键产生的输入
 72         /// </summary>
 73         /// <param name="sender"></param>
 74         /// <param name="e"></param>
 75         void AssociatedObject_KeyDown(object sender, KeyEventArgs e)
 76         {
 77             bool handled = true;
 78             //不进行过滤
 79             if (TextBoxFilterOptions == TextBoxFilterOptions.None ||
 80                 KeyboardHelper.IsControlKeys(e.Key))
 81             {
 82                 handled = false;
 83             }
 84             //数字键
 85             if (handled && TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Numeric))
 86             {
 87                 handled = !KeyboardHelper.IsDigit(e.Key);
 88             }
 89             //小数点
 90             if (handled && TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Dot))
 91             {
 92                 handled = !(KeyboardHelper.IsDot(e.Key, e.PlatformKeyCode) && !_prevText.Contains("."));
 93                 if (KeyboardHelper.IsDot(e.Key, e.PlatformKeyCode) && _prevText.Contains("."))
 94                 {
 95                     //如果输入位置的下一个就是小数点,则将光标跳到小数点后面
 96                     if (this.AssociatedObject.SelectionStart< this.AssociatedObject.Text.Length && _prevText[this.AssociatedObject.SelectionStart] == '.')
 97                     {
 98                         this.AssociatedObject.SelectionStart++;
 99                     }                    
100                 }
101             }
102             //字母
103             if (handled && TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Character))
104             {
105                 handled = !KeyboardHelper.IsDot(e.Key);
106             }
107             e.Handled = handled;
108         }
109 
110         #endregion
111 
112         #region Private Methods
113 
114         /// <summary>
115         /// 判断是否符合规则
116         /// </summary>
117         /// <param name="c"></param>
118         /// <returns></returns>
119         private bool IsValidChar(char c)
120         {
121             if (TextBoxFilterOptions == TextBoxFilterOptions.None)
122             {
123                 return true;
124             }
125             else if (TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Numeric) &&
126                 '0' <= c && c <= '9')
127             {
128                 return true;
129             }
130             else if (TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Dot) &&
131                 c == '.')
132             {
133                 return true;
134             }
135             else if (TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Character)) 
136             {
137                 if (('A' <= c && c <= 'Z'|| ('a' <= c && c <= 'z'))
138                 {
139                     return true;
140                 }
141             }
142             return false;
143         }
144 
145         /// <summary>
146         /// 判断文本是否符合规则
147         /// </summary>
148         /// <param name="text"></param>
149         /// <returns></returns>
150         private bool IsValidText(string text)
151         {
152             //只能有一个小数点
153             if (text.IndexOf('.'!= text.LastIndexOf('.'))
154             {
155                 return false;
156             }
157 
158             foreach (char c in text)
159             {
160                 if (!IsValidChar(c))
161                 {
162                     return false;
163                 }
164             }
165             return true;
166         }
167 
168         #endregion
169     }
170 

TextBoxFilterBehavior类主要的实现思路和代码就是这样,希望能给需要的朋友一定的帮助,NumericBox类的实现思路及相关代码我将在下篇文章中给出,敬请关注。

 

posted @ 2010-06-25 08:06  大气象  阅读(7612)  评论(12编辑  收藏  举报
http://www.tianqiweiqi.com