WPF TextBox 仅允许输入数字

因为在 IValueConverter 实现中,当文本不能转换为目标类型时返回 DependencyProperty.UnsetValue ,Validation.GetHasError 返回 true ,为何要绕一个圈让用户输入不能转换的文本,然后再获取错误状态呢?不如直接不让用户输入错误文本,于是写了一个 Behavior 派生类:

 

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Windows;
 7 using System.Windows.Controls;
 8 using System.Windows.Input;
 9 using System.Windows.Interactivity;
10 
11 namespace WpfApplication6
12 {
13     public class OnlyDigitalBehavior : Behavior<TextBox>
14     {
15         public Type DigitalType
16         {
17             get { return (Type)GetValue(DigitalTypeProperty); }
18             set { SetValue(DigitalTypeProperty, value); }
19         }
20 
21         public static readonly DependencyProperty DigitalTypeProperty =
22             DependencyProperty.Register("DigitalType", typeof(Type), typeof(OnlyDigitalBehavior), new PropertyMetadata());
23 
24 
25         protected override void OnAttached()
26         {
27             base.OnAttached();
28             this.AssociatedObject.PreviewTextInput += AssociatedObject_PreviewTextInput;
29             DataObject.AddPastingHandler(this.AssociatedObject, AssociatedObject_Pasting);
30             InputMethod.SetIsInputMethodEnabled(this.AssociatedObject, false);
31         }
32 
33         private void AssociatedObject_Pasting(object sender, DataObjectPastingEventArgs e)
34         {
35             e.CancelCommand();
36         }
37 
38         protected override void OnDetaching()
39         {
40             base.OnDetaching();
41             this.AssociatedObject.PreviewTextInput -= AssociatedObject_PreviewTextInput;
42             DataObject.RemovePastingHandler(this.AssociatedObject, AssociatedObject_Pasting);
43         }
44 
45 
46         private void AssociatedObject_PreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e)
47         {
48             TextBox textBox = sender as TextBox;
49             Type digitalType = this.DigitalType;
50             if (textBox == null)
51             {
52                 return;
53             }
54             if (digitalType == typeof(Int16))
55             {
56                 Int16 i = 0;
57                 if (Int16.TryParse(textBox.Text + e.Text, out i))
58                 {
59                     return;
60                 }
61             }
62             else if (digitalType == typeof(Int32))
63             {
64                 Int32 i = 0;
65                 if (Int32.TryParse(textBox.Text + e.Text, out i))
66                 {
67                     return;
68                 }
69             }
70             else if (digitalType == typeof(Int64))
71             {
72                 Int64 i = 0;
73                 if (Int64.TryParse(textBox.Text + e.Text, out i))
74                 {
75                     return;
76                 }
77             }
78             else if (digitalType == typeof(double))
79             {
80                 double d = 0;
81                 if (double.TryParse(textBox.Text + e.Text, out d))
82                 {
83                     return;
84                 }
85             }
86             else if (digitalType == typeof(decimal))
87             {
88                 decimal d = 0;
89                 if (decimal.TryParse(textBox.Text + e.Text, out d))
90                 {
91                     return;
92                 }
93             }
94             e.Handled = true;
95         }
96     }
97 }

 

InputMethod.SetIsInputMethodEnabled(this.AssociatedObject, false); 作用是屏蔽输入法。

以下是测试View:

 1 <Window x:Class="WpfApplication6.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
 5         xmlns:local="clr-namespace:WpfApplication6"
 6         xmlns:sys="clr-namespace:System;assembly=mscorlib"
 7         Title="MainWindow" Height="350" Width="525">
 8     <StackPanel>
 9         <TextBlock Margin="3">Int16</TextBlock>
10         <TextBox Margin="3">
11             <i:Interaction.Behaviors>
12                 <local:OnlyDigitalBehavior DigitalType="{x:Type sys:Int16}" />
13             </i:Interaction.Behaviors>
14         </TextBox>
15         <TextBlock Margin="3">Int32</TextBlock>
16         <TextBox Margin="3">
17             <i:Interaction.Behaviors>
18                 <local:OnlyDigitalBehavior DigitalType="{x:Type sys:Int32}" />
19             </i:Interaction.Behaviors>
20         </TextBox>
21         <TextBlock Margin="3">Int64</TextBlock>
22         <TextBox Margin="3">
23             <i:Interaction.Behaviors>
24                 <local:OnlyDigitalBehavior DigitalType="{x:Type sys:Int64}" />
25             </i:Interaction.Behaviors>
26         </TextBox>
27         <TextBlock Margin="3">Double</TextBlock>
28         <TextBox Margin="3">
29             <i:Interaction.Behaviors>
30                 <local:OnlyDigitalBehavior DigitalType="{x:Type sys:Double}" />
31             </i:Interaction.Behaviors>
32         </TextBox>
33         <TextBlock Margin="3">Decimal</TextBlock>
34         <TextBox Margin="3">
35             <i:Interaction.Behaviors>
36                 <local:OnlyDigitalBehavior DigitalType="{x:Type sys:Decimal}" />
37             </i:Interaction.Behaviors>
38         </TextBox>
39     </StackPanel>
40 </Window>

如果大家有更好的实现方法欢迎赐教!

再来一个支持粘贴的:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Threading.Tasks;
  6 using System.Windows;
  7 using System.Windows.Controls;
  8 using System.Windows.Input;
  9 using System.Windows.Interactivity;
 10 
 11 namespace WpfApplication6
 12 {
 13     public class OnlyDigitalBehavior : Behavior<TextBox>
 14     {
 15         private string lastRight = null;
 16 
 17         public Type DigitalType
 18         {
 19             get { return (Type)GetValue(DigitalTypeProperty); }
 20             set { SetValue(DigitalTypeProperty, value); }
 21         }
 22 
 23         public static readonly DependencyProperty DigitalTypeProperty =
 24             DependencyProperty.Register("DigitalType", typeof(Type), typeof(OnlyDigitalBehavior), new PropertyMetadata());
 25 
 26 
 27         protected override void OnAttached()
 28         {
 29             base.OnAttached();
 30             this.AssociatedObject.TextChanged += AssociatedObject_TextChanged;
 31             InputMethod.SetIsInputMethodEnabled(this.AssociatedObject, false);
 32         }
 33 
 34         protected override void OnDetaching()
 35         {
 36             base.OnDetaching();
 37             this.AssociatedObject.TextChanged -= AssociatedObject_TextChanged;
 38         }
 39 
 40         private void AssociatedObject_TextChanged(object sender, TextChangedEventArgs e)
 41         {
 42             TextBox textBox = sender as TextBox;
 43             Type digitalType = this.DigitalType;
 44             if (textBox == null)
 45             {
 46                 return;
 47             }
 48             if ((IsDigital(digitalType,textBox.Text) || string.IsNullOrEmpty(textBox.Text)) && lastRight != textBox.Text)
 49             {
 50                 lastRight = textBox.Text;
 51             }
 52             else if (textBox.Text != lastRight)
 53             {
 54                 textBox.Text = lastRight;
 55                 textBox.SelectionStart = textBox.Text.Length;
 56             }
 57         }
 58 
 59         private bool IsDigital(Type targetType,string digitalString)
 60         {
 61             if (targetType == typeof(Int16))
 62             {
 63                 Int16 i = 0;
 64                 if (Int16.TryParse(digitalString, out i))
 65                 {
 66                     return true;
 67                 }
 68             }
 69             else if (targetType == typeof(Int32))
 70             {
 71                 Int32 i = 0;
 72                 if (Int32.TryParse(digitalString, out i))
 73                 {
 74                     return true;
 75                 }
 76             }
 77             else if (targetType == typeof(Int64))
 78             {
 79                 Int64 i = 0;
 80                 if (Int64.TryParse(digitalString, out i))
 81                 {
 82                     return true;
 83                 }
 84             }
 85             else if (targetType == typeof(double))
 86             {
 87                 double d = 0;
 88                 if (double.TryParse(digitalString, out d))
 89                 {
 90                     return true;
 91                 }
 92             }
 93             else if (targetType == typeof(decimal))
 94             {
 95                 decimal d = 0;
 96                 if (decimal.TryParse(digitalString, out d))
 97                 {
 98                     return true;
 99                 }
100             }
101             return false;
102         }
103     }
104 }

 

posted @ 2016-05-09 10:41  无眠0007  阅读(1359)  评论(0编辑  收藏  举报