WPF 自定义TextBox,可控制键盘输入内容

非原创,整理之前的代码的时候找出来的,可用,与大家分享一下!

 

  1   public class NumbericBoxWithZero : NumericBox

  2     {

  3         public NumbericBoxWithZero()

  4             : base()

  5         {

  6 

  7 

  8         }

  9         protected override void SetTextAndSelection(string text)

 10         {

 11             if (text.IndexOf('.') == -1)

 12             {

 13                 text = text + ".00";

 14             }

 15             else

 16             {

 17                 if (text.IndexOf('.') != text.Length - 1)

 18                 {

 19                     string front = text.Substring(0,text.IndexOf('.'));

 20                     string back = text.Substring(text.IndexOf('.') + 1, text.Length - text.IndexOf('.') - 1);

 21                     if(back != "00")

 22                         text = string.Format("{0}.{1:d2}",front,int.Parse(back));

 23                 }

 24             }

 25             base.SetTextAndSelection(text);

 26         }

 27     }

 28     /// <summary>

 29     /// NumericBox功能设计

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

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

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

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

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

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

 36     /// </summary>

 37     public class NumericBox : TextBox

 38     {

 39         #region Dependency Properties

 40         /// <summary>

 41         /// 最大小数点位数

 42         /// </summary>

 43         public int MaxFractionDigits

 44         {

 45             get { return (int)GetValue(MaxFractionDigitsProperty); }

 46             set { SetValue(MaxFractionDigitsProperty, value); }

 47         }

 48         // Using a DependencyProperty as the backing store for MaxFractionDigits.  This enables animation, styling, binding, etc...

 49         public static readonly DependencyProperty MaxFractionDigitsProperty =

 50             DependencyProperty.Register("MaxFractionDigits", typeof(int), typeof(NumericBox), new PropertyMetadata(2));

 51 

 52         /// <summary>

 53         /// 不足位数是否补零

 54         /// </summary>

 55         public bool IsPadding

 56         {

 57             get { return (bool)GetValue(IsPaddingProperty); }

 58             set { SetValue(IsPaddingProperty, value); }

 59         }

 60         // Using a DependencyProperty as the backing store for IsPadding.  This enables animation, styling, binding, etc...

 61         public static readonly DependencyProperty IsPaddingProperty =

 62             DependencyProperty.Register("IsPadding", typeof(bool), typeof(NumericBox), new PropertyMetadata(true));

 63 

 64         #endregion

 65 

 66         public NumericBox()

 67         {

 68             TextBoxFilterBehavior behavior = new TextBoxFilterBehavior();

 69             behavior.TextBoxFilterOptions = TextBoxFilterOptions.Numeric | TextBoxFilterOptions.Dot;

 70             Interaction.GetBehaviors(this).Add(behavior);

 71             this.TextChanged += new TextChangedEventHandler(NumericBox_TextChanged);

 72         }

 73 

 74         /// <summary>

 75         /// 设置Text文本以及光标位置

 76         /// </summary>

 77         /// <param name="text"></param>

 78         protected virtual void SetTextAndSelection(string text)

 79         {

 80             //保存光标位置

 81             int selectionIndex = this.SelectionStart;

 82             this.Text = text;

 83             //恢复光标位置 系统会自动处理光标位置超出文本长度的情况

 84             this.SelectionStart = selectionIndex;

 85         }

 86 

 87         /// <summary>

 88         /// 去掉开头部分多余的0

 89         /// </summary>

 90         private void TrimZeroStart()

 91         {

 92             string resultText = this.Text;

 93             //计算开头部分0的个数

 94             int zeroCount = 0;

 95             foreach (char c in this.Text)

 96             {

 97                 if (c == '0') { zeroCount++; }

 98                 else { break; }

 99             }

100 

101             //当前文本中包含小数点

102             if (this.Text.Contains('.'))

103             {

104                 //0后面跟的不是小数点,则删除全部的0

105                 if (this.Text[zeroCount] != '.')

106                 {

107                     resultText = this.Text.TrimStart('0');

108                 }

109                 //否则,保留一个0

110                 else if (zeroCount > 1)

111                 {

112                     resultText = this.Text.Substring(zeroCount - 1);

113                 }

114             }

115             //当前文本中不包含小数点,则保留一个0,并在其后加一个小数点,并将光标设置到小数点前

116             else if (zeroCount > 0)

117             {

118                 resultText = "0." + this.Text.TrimStart('0');

119                 this.SelectionStart = 1;

120             }

121 

122             SetTextAndSelection(resultText);

123         }

124 

125         void NumericBox_TextChanged(object sender, TextChangedEventArgs e)

126         {

127             int decimalIndex = this.Text.IndexOf('.');

128             if (decimalIndex >= 0)

129             {

130                 //小数点后的位数

131                 int lengthAfterDecimal = this.Text.Length - decimalIndex - 1;

132                 if (lengthAfterDecimal > MaxFractionDigits)

133                 {

134                     SetTextAndSelection(this.Text.Substring(0, this.Text.Length - (lengthAfterDecimal - MaxFractionDigits)));

135                 }

136                 else if (IsPadding)

137                 {

138                     SetTextAndSelection(this.Text.PadRight(this.Text.Length + MaxFractionDigits - lengthAfterDecimal, '0'));

139                 }

140             }

141             TrimZeroStart();

142         }

143     }

144     /// <summary>

145     /// TextBox筛选行为,过滤不需要的按键

146     /// </summary>

147     public class TextBoxFilterBehavior : Behavior<TextBox>

148     {

149         private string _prevText = string.Empty;

150         public TextBoxFilterBehavior()

151         {

152         }

153         #region Dependency Properties

154         /// <summary>

155         /// TextBox筛选选项,这里选择的为过滤后剩下的按键

156         /// 控制键不参与筛选,可以多选组合

157         /// </summary>

158         public TextBoxFilterOptions TextBoxFilterOptions

159         {

160             get { return (TextBoxFilterOptions)GetValue(TextBoxFilterOptionsProperty); }

161             set { SetValue(TextBoxFilterOptionsProperty, value); }

162         }

163 

164         // Using a DependencyProperty as the backing store for TextBoxFilterOptions.  This enables animation, styling, binding, etc...

165         public static readonly DependencyProperty TextBoxFilterOptionsProperty =

166             DependencyProperty.Register("TextBoxFilterOptions", typeof(TextBoxFilterOptions), typeof(TextBoxFilterBehavior), new PropertyMetadata(TextBoxFilterOptions.None));

167         #endregion

168 

169         protected override void OnAttached()

170         {

171             base.OnAttached();

172             this.AssociatedObject.KeyDown += new KeyEventHandler(AssociatedObject_KeyDown);

173             this.AssociatedObject.TextChanged += new TextChangedEventHandler(AssociatedObject_TextChanged);

174         }

175 

176         protected override void OnDetaching()

177         {

178             base.OnDetaching();

179             this.AssociatedObject.KeyDown -= new KeyEventHandler(AssociatedObject_KeyDown);

180             this.AssociatedObject.TextChanged -= new TextChangedEventHandler(AssociatedObject_TextChanged);

181         }

182 

183         #region Events

184 

185         /// <summary>

186         /// 处理通过其它手段进行的输入

187         /// </summary>

188         /// <param name="sender"></param>

189         /// <param name="e"></param>

190         void AssociatedObject_TextChanged(object sender, TextChangedEventArgs e)

191         {

192             //如果符合规则,就保存下来

193             if (IsValidText(this.AssociatedObject.Text))

194             {

195                 _prevText = this.AssociatedObject.Text;

196             }

197             //如果不符合规则,就恢复为之前保存的值

198             else

199             {

200                 int selectIndex = this.AssociatedObject.SelectionStart - (this.AssociatedObject.Text.Length - _prevText.Length);

201                 this.AssociatedObject.Text = _prevText;

202 

203                 if (selectIndex < 0)

204                     selectIndex = 0;

205 

206                 this.AssociatedObject.SelectionStart = selectIndex;

207             }

208 

209         }

210 

211         /// <summary>

212         /// 处理按键产生的输入

213         /// </summary>

214         /// <param name="sender"></param>

215         /// <param name="e"></param>

216         void AssociatedObject_KeyDown(object sender, KeyEventArgs e)

217         {

218             bool handled = true;

219             //不进行过滤

220             if (TextBoxFilterOptions == TextBoxFilterOptions.None ||

221                 KeyboardHelper.IsControlKeys(e.Key))

222             {

223                 handled = false;

224             }

225             //数字键

226             if (handled && TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Numeric))

227             {

228                 handled = !KeyboardHelper.IsDigit(e.Key);

229             }

230             //小数点

231             //if (handled && TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Dot))

232             //{

233             //    handled = !(KeyboardHelper.IsDot(e.Key, e.PlatformKeyCode) && !_prevText.Contains("."));

234             //    if (KeyboardHelper.IsDot(e.Key, e.PlatformKeyCode) && _prevText.Contains("."))

235             //    {

236             //        //如果输入位置的下一个就是小数点,则将光标跳到小数点后面

237             //        if (this.AssociatedObject.SelectionStart< this.AssociatedObject.Text.Length && _prevText[this.AssociatedObject.SelectionStart] == '.')

238             //        {

239             //            this.AssociatedObject.SelectionStart++;

240             //        }                    

241             //    }

242             //}

243             if (handled && TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Dot))

244             {

245                 handled = !(KeyboardHelper.IsDot(e.Key) && !_prevText.Contains("."));

246                 if (KeyboardHelper.IsDot(e.Key) && _prevText.Contains("."))

247                 {

248                     //如果输入位置的下一个就是小数点,则将光标跳到小数点后面

249                     if (this.AssociatedObject.SelectionStart < this.AssociatedObject.Text.Length && _prevText[this.AssociatedObject.SelectionStart] == '.')

250                     {

251                         this.AssociatedObject.SelectionStart++;

252                     }

253                 }

254             }

255             //字母

256             if (handled && TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Character))

257             {

258                 handled = !KeyboardHelper.IsDot(e.Key);

259             }

260             e.Handled = handled;

261         }

262 

263         #endregion

264 

265         #region Private Methods

266         /// <summary>

267         /// 判断是否符合规则

268         /// </summary>

269         /// <param name="c"></param>

270         /// <returns></returns>

271         private bool IsValidChar(char c)

272         {

273             if (TextBoxFilterOptions == TextBoxFilterOptions.None)

274             {

275                 return true;

276             }

277             else if (TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Numeric) &&

278                 '0' <= c && c <= '9')

279             {

280                 return true;

281             }

282             else if (TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Dot) &&

283                 c == '.')

284             {

285                 return true;

286             }

287             else if (TextBoxFilterOptions.ContainsOption(TextBoxFilterOptions.Character))

288             {

289                 if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'))

290                 {

291                     return true;

292                 }

293             }

294             return false;

295         }

296 

297         /// <summary>

298         /// 判断文本是否符合规则

299         /// </summary>

300         /// <param name="text"></param>

301         /// <returns></returns>

302         private bool IsValidText(string text)

303         {

304             //只能有一个小数点

305             if (text.IndexOf('.') != text.LastIndexOf('.'))

306             {

307                 return false;

308             }

309             foreach (char c in text)

310             {

311                 if (!IsValidChar(c))

312                 {

313                     return false;

314                 }

315             }

316             return true;

317         }

318         #endregion

319     }

320     /// <summary>

321     /// TextBox筛选选项

322     /// </summary>

323     [Flags]

324     public enum TextBoxFilterOptions

325     {

326         /// <summary>

327         /// 不采用任何筛选

328         /// </summary>

329         None = 0,

330         /// <summary>

331         /// 数字类型不参与筛选

332         /// </summary>

333         Numeric = 1,

334         /// <summary>

335         /// 字母类型不参与筛选

336         /// </summary>

337         Character = 2,

338         /// <summary>

339         /// 小数点不参与筛选

340         /// </summary>

341         Dot = 4,

342         /// <summary>

343         /// 其它类型不参与筛选

344         /// </summary>

345         Other = 8

346     }

347 

348     /// <summary>

349     /// TextBox筛选选项枚举扩展方法

350     /// </summary>

351     public static class TextBoxFilterOptionsExtension

352     {

353         /// <summary>

354         /// 在全部的选项中是否包含指定的选项

355         /// </summary>

356         /// <param name="allOptions">所有的选项</param>

357         /// <param name="option">指定的选项</param>

358         /// <returns></returns>

359         public static bool ContainsOption(this TextBoxFilterOptions allOptions, TextBoxFilterOptions option)

360         {

361             return (allOptions & option) == option;

362         }

363     }

364     /// <summary>

365     /// 键盘操作帮助类

366     /// </summary>

367     public class KeyboardHelper

368     {

369         /// <summary>

370         /// 键盘上的句号键

371         /// </summary>

372         public const int OemPeriod = 190;

373 

374         #region Fileds

375 

376         /// <summary>

377         /// 控制键

378         /// </summary>

379         private static readonly List<Key> _controlKeys = new List<Key>

380                                                              {

381                                                                  Key.Back,

382                                                                  Key.CapsLock,

383                                                                  //Key.Ctrl,

384                                                                  Key.Down,

385                                                                  Key.End,

386                                                                  Key.Enter,

387                                                                  Key.Escape,

388                                                                  Key.Home,

389                                                                  Key.Insert,

390                                                                  Key.Left,

391                                                                  Key.PageDown,

392                                                                  Key.PageUp,

393                                                                  Key.Right,

394                                                                  //Key.Shift,

395                                                                  Key.Tab,

396                                                                  Key.Up

397                                                              };

398 

399         #endregion

400 

401         /// <summary>

402         /// 是否是数字键

403         /// </summary>

404         /// <param name="key">按键</param>

405         /// <returns></returns>

406         public static bool IsDigit(Key key)

407         {

408             bool shiftKey = (Keyboard.Modifiers & ModifierKeys.Shift) != 0;

409             bool retVal;

410             //按住shift键后,数字键并不是数字键

411             if (key >= Key.D0 && key <= Key.D9 && !shiftKey)

412             {

413                 retVal = true;

414             }

415             else

416             {

417                 retVal = key >= Key.NumPad0 && key <= Key.NumPad9;

418             }

419             return retVal;

420         }

421 

422         /// <summary>

423         /// 是否是控制键

424         /// </summary>

425         /// <param name="key">按键</param>

426         /// <returns></returns>

427         public static bool IsControlKeys(Key key)

428         {

429             return _controlKeys.Contains(key);

430         }

431 

432         /// <summary>

433         /// 是否是小数点

434         /// Silverlight中无法识别问号左边的那个小数点键

435         /// 只能识别小键盘中的小数点

436         /// </summary>

437         /// <param name="key">按键</param>

438         /// <returns></returns>

439         public static bool IsDot(Key key)

440         {

441             bool shiftKey = (Keyboard.Modifiers & ModifierKeys.Shift) != 0;

442             bool flag = false;

443             if (key == Key.Decimal)

444             {

445                 flag = true;

446             }

447             if (key == Key.OemPeriod && !shiftKey)

448             {

449                 flag = true;

450             }

451             return flag;

452         }

453 

454         /// <summary>

455         /// 是否是小数点

456         /// </summary>

457         /// <param name="key">按键</param>

458         /// <param name="keyCode">平台相关的按键代码</param>

459         /// <returns></returns>

460         public static bool IsDot(Key key, int keyCode)

461         {

462 

463             //return IsDot(key) || (key == Key.Unknown && keyCode == OemPeriod);

464             return IsDot(key) || (keyCode == OemPeriod);

465         }

466 

467         /// <summary>

468         /// 是否是字母键

469         /// </summary>

470         /// <param name="key">按键</param>

471         /// <returns></returns>

472         public static bool IsCharacter(Key key)

473         {

474             return key >= Key.A && key <= Key.Z;

475         }

476     }
View Code

使用:

 <Controls:NumericBox Grid.Column="3" Grid.Row="11"

                                    Width="200"  Height="30" Text="{Binding old,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"

                                    CustomTextWrapping="NoWrap" CustomTextHeight="26" CustomTextWidth="170"

                                    BgForeground="{StaticResource DialogTextBgForeground}" 

                                    CustomBorderColor="{StaticResource DialogTextBorderColor}" CustomBgColor="{StaticResource DialogTextBgColor}" >

                <i:Interaction.Behaviors>

                    <Controls:TextBoxFilterBehavior TextBoxFilterOptions="Numeric"/>  <!--可以选择输入数字,小数点等-->

                </i:Interaction.Behaviors>

            </Controls:NumericBox>

 

你可能感兴趣的:(text)