namespace VideoBrowser.Extensions { using System.Windows; using System.Windows.Controls; using System.Windows.Input; using VideoBrowser.Helpers; /// /// Defines the . /// public static class TextBoxExtension { #region Fields public static readonly DependencyProperty CaretIndexProperty = DependencyProperty.RegisterAttached(nameof(CaretIndexProperty).Name(), typeof(int), typeof(TextBoxExtension), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnCaretIndexChanged)); public static readonly DependencyProperty IsClickToSelectAllProperty = DependencyProperty.RegisterAttached(nameof(IsClickToSelectAllProperty).Name(), typeof(bool), typeof(TextBoxExtension), new PropertyMetadata(false, OnIsClickToSelectAllChanged)); public static readonly DependencyProperty SelectionLengthProperty = DependencyProperty.RegisterAttached(nameof(SelectionLengthProperty).Name(), typeof(int), typeof(TextBoxExtension), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSelectionLengthChanged)); public static readonly DependencyProperty SelectionStartProperty = DependencyProperty.RegisterAttached(nameof(SelectionStartProperty).Name(), typeof(int), typeof(TextBoxExtension), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSelectionStartChanged)); public static readonly DependencyProperty TrackCaretIndexProperty = DependencyProperty.RegisterAttached(nameof(TrackCaretIndexProperty).Name(), typeof(bool), typeof(TextBoxExtension), new PropertyMetadata(false, OnTrackCaretIndexChanged)); #endregion Fields #region Methods /// /// The GetCaretIndex. /// /// The obj. /// The . public static int GetCaretIndex(DependencyObject obj) => (int)obj.GetValue(CaretIndexProperty); /// /// The GetIsClickToSelectAll. /// /// The obj. /// The . public static bool GetIsClickToSelectAll(DependencyObject obj) => (bool)obj.GetValue(IsClickToSelectAllProperty); /// /// The GetSelectionLength. /// /// The obj. /// The . public static int GetSelectionLength(DependencyObject obj) => (int)obj.GetValue(SelectionLengthProperty); /// /// The GetSelectionStart. /// /// The obj. /// The . public static int GetSelectionStart(DependencyObject obj) => (int)obj.GetValue(SelectionStartProperty); /// /// The GetTrackCaretIndex. /// /// The obj. /// The . public static bool GetTrackCaretIndex(DependencyObject obj) => (bool)obj.GetValue(TrackCaretIndexProperty); /// /// The SetCaretIndex. /// /// The obj. /// The value. public static void SetCaretIndex(DependencyObject obj, int value) => obj.SetValue(CaretIndexProperty, value); /// /// The SetIsClickToSelectAll. /// /// The obj. /// The value. public static void SetIsClickToSelectAll(DependencyObject obj, bool value) => obj.SetValue(IsClickToSelectAllProperty, value); /// /// The SetSelectionLength. /// /// The obj. /// The value. public static void SetSelectionLength(DependencyObject obj, int value) => obj.SetValue(SelectionLengthProperty, value); /// /// The SetSelectionStart. /// /// The obj. /// The value. public static void SetSelectionStart(DependencyObject obj, int value) => obj.SetValue(SelectionStartProperty, value); /// /// The SetTrackCaretIndex. /// /// The obj. /// The value. public static void SetTrackCaretIndex(DependencyObject obj, bool value) => obj.SetValue(TrackCaretIndexProperty, value); /// /// The OnCaretIndexChanged. /// /// The d. /// The e. private static void OnCaretIndexChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (!(d is TextBox textbox)) { return; } var caretIndex = (int)e.NewValue; if (textbox.CaretIndex != caretIndex) { textbox.CaretIndex = caretIndex; } } /// /// The OnIsClickToSelectAllChanged. /// /// The d. /// The e. private static void OnIsClickToSelectAllChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (!(d is TextBox textbox)) { return; } var oldValue = (bool)e.OldValue; var newValue = (bool)e.NewValue; if (!oldValue && newValue) // If changed from false to true { textbox.PreviewMouseLeftButtonDown += OnTextbox_PreviewMouseLeftButtonDown; textbox.MouseDoubleClick += OnTextbox_MouseDoubleClick; } else if (oldValue && !newValue) // If changed from true to false { textbox.PreviewMouseLeftButtonDown -= OnTextbox_PreviewMouseLeftButtonDown; textbox.MouseDoubleClick -= OnTextbox_MouseDoubleClick; } } /// /// The OnSelectionChanged. /// /// The sender. /// The e. private static void OnSelectionChanged(object sender, RoutedEventArgs e) { if (sender is TextBox textbox) { SetCaretIndex(textbox, textbox.CaretIndex); SetSelectionStart(textbox, textbox.SelectionStart); SetSelectionLength(textbox, textbox.SelectionLength); } } /// /// The OnSelectionLengthChanged. /// /// The d. /// The e. private static void OnSelectionLengthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (!(d is TextBox textbox)) { return; } var selectionLength = (int)e.NewValue; if (textbox.SelectionLength != selectionLength) { textbox.SelectionLength = selectionLength; } } /// /// The OnSelectionStartChanged. /// /// The d. /// The e. private static void OnSelectionStartChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (!(d is TextBox textbox)) { return; } var selectionStart = (int)e.NewValue; if (textbox.SelectionStart != selectionStart) { textbox.SelectionStart = selectionStart; } } /// /// The OnTextbox_MouseDoubleClick. /// /// The sender. /// The e. private static void OnTextbox_MouseDoubleClick(object sender, MouseButtonEventArgs e) { if (!(sender is TextBox textbox)) { return; } UIThreadHelper.DelayedInvokeAsync(() => { textbox.Focus(); textbox.SelectAll(); }, 200); } /// /// The OnTextbox_PreviewMouseLeftButtonDown. /// /// The sender. /// The e. private static void OnTextbox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { if (!(sender is TextBox textbox)) { return; } if (!textbox.IsFocused) { UIThreadHelper.DelayedInvokeAsync(() => { textbox.Focus(); textbox.SelectAll(); }, 200); } } /// /// The OnTrackCaretIndexChanged. /// /// The d. /// The e. private static void OnTrackCaretIndexChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (!(d is TextBox textbox)) { return; } var oldValue = (bool)e.OldValue; var newValue = (bool)e.NewValue; if (!oldValue && newValue) // If changed from false to true { textbox.SelectionChanged += OnSelectionChanged; } else if (oldValue && !newValue) // If changed from true to false { textbox.SelectionChanged -= OnSelectionChanged; } } #endregion Methods } }