using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; namespace SourceGit.Helpers { /// /// Attached properties to TextBox. /// public static class TextBoxHelper { /// /// Auto scroll on text changed or selection changed. /// public static readonly DependencyProperty AutoScrollProperty = DependencyProperty.RegisterAttached( "AutoScroll", typeof(bool), typeof(TextBoxHelper), new PropertyMetadata(false, OnAutoScrollChanged)); /// /// Placeholder property /// public static readonly DependencyProperty PlaceholderProperty = DependencyProperty.RegisterAttached( "Placeholder", typeof(string), typeof(TextBoxHelper), new PropertyMetadata(string.Empty, OnPlaceholderChanged)); /// /// Vertical alignment for placeholder. /// public static readonly DependencyProperty PlaceholderBaselineProperty = DependencyProperty.RegisterAttached( "PlaceholderBaseline", typeof(AlignmentY), typeof(TextBoxHelper), new PropertyMetadata(AlignmentY.Center)); /// /// Property to store generated placeholder brush. /// public static readonly DependencyProperty PlaceholderBrushProperty = DependencyProperty.RegisterAttached( "PlaceholderBrush", typeof(Brush), typeof(TextBoxHelper), new PropertyMetadata(Brushes.Transparent)); /// /// Setter for AutoScrollProperty /// /// /// public static void SetAutoScroll(UIElement element, bool enabled) { element.SetValue(AutoScrollProperty, enabled); } /// /// Getter for AutoScrollProperty /// /// /// public static bool GetAutoScroll(UIElement element) { return (bool)element.GetValue(AutoScrollProperty); } /// /// Triggered when AutoScroll property changed. /// /// /// public static void OnAutoScrollChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var textBox = d as TextBox; if (textBox == null) return; textBox.SelectionChanged -= UpdateScrollOnSelectionChanged; if ((bool)e.NewValue == true) { textBox.SelectionChanged += UpdateScrollOnSelectionChanged; } } /// /// Triggered when placeholder changed. /// /// /// private static void OnPlaceholderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var textBox = d as TextBox; if (textBox != null) textBox.Loaded += OnTextLoaded; } /// /// Setter for Placeholder property /// /// /// public static void SetPlaceholder(UIElement element, string value) { element.SetValue(PlaceholderProperty, value); } /// /// Getter for Placeholder property /// /// /// public static string GetPlaceholder(UIElement element) { return (string)element.GetValue(PlaceholderProperty); } /// /// Setter for PlaceholderBaseline property /// /// /// public static void SetPlaceholderBaseline(UIElement element, AlignmentY align) { element.SetValue(PlaceholderBaselineProperty, align); } /// /// Setter for PlaceholderBaseline property. /// /// /// public static AlignmentY GetPlaceholderBaseline(UIElement element) { return (AlignmentY)element.GetValue(PlaceholderBaselineProperty); } /// /// Setter for PlaceholderBrush property. /// /// /// public static void SetPlaceholderBrush(UIElement element, Brush value) { element.SetValue(PlaceholderBrushProperty, value); } /// /// Getter for PlaceholderBrush property. /// /// /// public static Brush GetPlaceholderBrush(UIElement element) { return (Brush)element.GetValue(PlaceholderBrushProperty); } /// /// Set placeholder as background when TextBox was loaded. /// /// /// private static void OnTextLoaded(object sender, RoutedEventArgs e) { var textBox = sender as TextBox; if (textBox == null) return; Label placeholder = new Label(); placeholder.Content = textBox.GetValue(PlaceholderProperty); VisualBrush brush = new VisualBrush(); brush.AlignmentX = AlignmentX.Left; brush.AlignmentY = GetPlaceholderBaseline(textBox); brush.TileMode = TileMode.None; brush.Stretch = Stretch.None; brush.Opacity = 0.3; brush.Visual = placeholder; textBox.SetValue(PlaceholderBrushProperty, brush); textBox.Background = brush; textBox.TextChanged += UpdatePlaceholder; UpdatePlaceholder(textBox, null); } /// /// Dynamically hide/show placeholder. /// /// /// private static void UpdatePlaceholder(object sender, RoutedEventArgs e) { var textBox = sender as TextBox; if (string.IsNullOrEmpty(textBox.Text)) { textBox.Background = textBox.GetValue(PlaceholderBrushProperty) as Brush; } else { textBox.Background = Brushes.Transparent; } } /// /// /// /// /// private static void UpdateScrollOnSelectionChanged(object sender, RoutedEventArgs e) { var textBox = sender as TextBox; if (textBox != null && textBox.IsFocused) { if (Mouse.LeftButton == MouseButtonState.Pressed && textBox.SelectionLength > 0) { var p = Mouse.GetPosition(textBox); if (p.X <= 8) { textBox.LineLeft(); } else if (p.X >= textBox.ActualWidth - 8) { textBox.LineRight(); } if (p.Y <= 8) { textBox.LineUp(); } else if (p.Y >= textBox.ActualHeight - 8) { textBox.LineDown(); } } else { var rect = textBox.GetRectFromCharacterIndex(textBox.CaretIndex); if (rect.Left <= 0) { textBox.ScrollToHorizontalOffset(textBox.HorizontalOffset + rect.Left); } else if (rect.Right >= textBox.ActualWidth) { textBox.ScrollToHorizontalOffset(textBox.HorizontalOffset + rect.Right); } if (rect.Top <= 0) { textBox.ScrollToVerticalOffset(textBox.VerticalOffset + rect.Top); } else if (rect.Bottom >= textBox.ActualHeight) { textBox.ScrollToVerticalOffset(textBox.VerticalOffset + rect.Bottom); } } } } } }