AllowableCharactersTextBoxBehavior.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Text.RegularExpressions;
  6. using System.Threading.Tasks;
  7. using System.Windows;
  8. using System.Windows.Controls;
  9. using System.Windows.Input;
  10. using System.Windows.Interactivity;
  11. namespace PixiEditor.Helpers.Behaviours
  12. {
  13. public class AllowableCharactersTextBoxBehavior : Behavior<TextBox>
  14. {
  15. public static readonly DependencyProperty RegularExpressionProperty =
  16. DependencyProperty.Register("RegularExpression", typeof(string), typeof(AllowableCharactersTextBoxBehavior),
  17. new FrameworkPropertyMetadata(".*"));
  18. public string RegularExpression
  19. {
  20. get
  21. {
  22. return (string)base.GetValue(RegularExpressionProperty);
  23. }
  24. set
  25. {
  26. base.SetValue(RegularExpressionProperty, value);
  27. }
  28. }
  29. public static readonly DependencyProperty MaxLengthProperty =
  30. DependencyProperty.Register("MaxLength", typeof(int), typeof(AllowableCharactersTextBoxBehavior),
  31. new FrameworkPropertyMetadata(int.MinValue));
  32. public int MaxLength
  33. {
  34. get
  35. {
  36. return (int)base.GetValue(MaxLengthProperty);
  37. }
  38. set
  39. {
  40. base.SetValue(MaxLengthProperty, value);
  41. }
  42. }
  43. protected override void OnAttached()
  44. {
  45. base.OnAttached();
  46. AssociatedObject.PreviewTextInput += OnPreviewTextInput;
  47. DataObject.AddPastingHandler(AssociatedObject, OnPaste);
  48. }
  49. private void OnPaste(object sender, DataObjectPastingEventArgs e)
  50. {
  51. if (e.DataObject.GetDataPresent(DataFormats.Text))
  52. {
  53. string text = Convert.ToString(e.DataObject.GetData(DataFormats.Text));
  54. if (!IsValid(text, true))
  55. {
  56. e.CancelCommand();
  57. }
  58. }
  59. else
  60. {
  61. e.CancelCommand();
  62. }
  63. }
  64. void OnPreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e)
  65. {
  66. e.Handled = !IsValid(e.Text, false);
  67. }
  68. protected override void OnDetaching()
  69. {
  70. base.OnDetaching();
  71. AssociatedObject.PreviewTextInput -= OnPreviewTextInput;
  72. DataObject.RemovePastingHandler(AssociatedObject, OnPaste);
  73. }
  74. private bool IsValid(string newText, bool paste)
  75. {
  76. return !ExceedsMaxLength(newText, paste) && Regex.IsMatch(newText, RegularExpression);
  77. }
  78. private bool ExceedsMaxLength(string newText, bool paste)
  79. {
  80. if (MaxLength == 0) return false;
  81. return LengthOfModifiedText(newText, paste) > MaxLength;
  82. }
  83. private int LengthOfModifiedText(string newText, bool paste)
  84. {
  85. var countOfSelectedChars = this.AssociatedObject.SelectedText.Length;
  86. var caretIndex = this.AssociatedObject.CaretIndex;
  87. string text = this.AssociatedObject.Text;
  88. if (countOfSelectedChars > 0 || paste)
  89. {
  90. text = text.Remove(caretIndex, countOfSelectedChars);
  91. return text.Length + newText.Length;
  92. }
  93. else
  94. {
  95. var insert = Keyboard.IsKeyToggled(Key.Insert);
  96. return insert && caretIndex < text.Length ? text.Length : text.Length + newText.Length;
  97. }
  98. }
  99. }
  100. }