TextBoxDateTimeMaskBehavior.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Windows;
  5. using System.Windows.Controls;
  6. using System.Windows.Forms;
  7. using System.Windows.Input;
  8. using Microsoft.Xaml.Behaviors;
  9. using Xceed.Wpf.Toolkit;
  10. using KeyEventArgs = System.Windows.Input.KeyEventArgs;
  11. using TextBox = System.Windows.Controls.TextBox;
  12. namespace InABox.WPF;
  13. public class TextBoxDateTimeMaskBehavior : Behavior<TextBox>
  14. {
  15. private bool bFirst = true;
  16. private List<Tuple<int, char>> _separators = new List<Tuple<int, char>>();
  17. private bool _isEnabled = true;
  18. private bool _previouslyEnabled = true;
  19. private string _format = "";
  20. public string Format
  21. {
  22. get => _format;
  23. set
  24. {
  25. _format = value;
  26. ReloadSeparators();
  27. }
  28. }
  29. public bool IsEnabled
  30. {
  31. get => _isEnabled;
  32. set
  33. {
  34. _isEnabled = value;
  35. if (AssociatedObject != null)
  36. AssociatedObject.IsEnabled = value;
  37. }
  38. }
  39. private void ReloadSeparators()
  40. {
  41. _separators.Clear();
  42. var formatted = String.Format("{0:"+_format+"}",DateTime.Now );
  43. int iOffset = 0;
  44. for (int i=0; i<formatted.Length; i++)
  45. {
  46. var ch = formatted[i];
  47. if (!Char.IsNumber(ch))
  48. {
  49. _separators.Add(new Tuple<int, char>(i - iOffset, ch));
  50. iOffset++;
  51. }
  52. }
  53. }
  54. public TextBoxDateTimeMaskBehavior(string? format, bool isEnabled = true)
  55. {
  56. Format = String.IsNullOrWhiteSpace(format)
  57. ? "dd/MM/yyyy HH:mm:ss"
  58. : format;
  59. _isEnabled = isEnabled;
  60. }
  61. protected override void OnAttached()
  62. {
  63. AssociatedObject.PreviewTextInput += PreviewTextInput;
  64. AssociatedObject.TextChanged += TextChanged;
  65. AssociatedObject.MouseDoubleClick += MouseDoubleClick;
  66. _previouslyEnabled = AssociatedObject.IsEnabled;
  67. AssociatedObject.IsEnabled = _isEnabled;
  68. base.OnAttached();
  69. }
  70. protected override void OnDetaching()
  71. {
  72. AssociatedObject.MouseDoubleClick -= MouseDoubleClick;
  73. AssociatedObject.TextChanged -= TextChanged;
  74. AssociatedObject.PreviewTextInput -= PreviewTextInput;
  75. AssociatedObject.IsEnabled = _previouslyEnabled;
  76. base.OnDetaching();
  77. }
  78. private void MouseDoubleClick(object sender, MouseButtonEventArgs e)
  79. {
  80. AssociatedObject.Text = String.Format("{0:" + Format + "}", DateTime.Now);
  81. }
  82. private void PreviewTextInput(object sender, TextCompositionEventArgs e)
  83. {
  84. bFirst = false;
  85. if (!int.TryParse(e.Text, out int _))
  86. e.Handled = true;
  87. }
  88. private void TextChanged(object sender, TextChangedEventArgs e)
  89. {
  90. var plaintext = AssociatedObject.Text?.Trim() ?? "";
  91. foreach (var separator in _separators)
  92. plaintext = plaintext.Replace(separator.Item2.ToString(), "");
  93. var decorated = plaintext;
  94. for (int i = _separators.Count - 1; i >= 0; i--)
  95. {
  96. if (plaintext.Length >= _separators[i].Item1)
  97. decorated = decorated.Insert(_separators[i].Item1, _separators[i].Item2.ToString());
  98. }
  99. AssociatedObject.Text = decorated;
  100. if (bFirst)
  101. AssociatedObject.SelectAll();
  102. else
  103. AssociatedObject.Select(AssociatedObject.Text.Length, 0);
  104. e.Handled = true;
  105. }
  106. }