I have a WPF application that contains a multiline TextBox that is being used to display debugging text output.
How can I set the TextBox so that as text is appended to
This solution is inspired by Scott Ferguson's solution with the attached property, but avoids storing an internal dictionary of associations and thereby has somewhat shorter code:
using System;
using System.Windows;
using System.Windows.Controls;
namespace AttachedPropertyTest
{
public static class TextBoxUtilities
{
public static readonly DependencyProperty AlwaysScrollToEndProperty = DependencyProperty.RegisterAttached("AlwaysScrollToEnd",
typeof(bool),
typeof(TextBoxUtilities),
new PropertyMetadata(false, AlwaysScrollToEndChanged));
private static void AlwaysScrollToEndChanged(object sender, DependencyPropertyChangedEventArgs e)
{
TextBox tb = sender as TextBox;
if (tb != null) {
bool alwaysScrollToEnd = (e.NewValue != null) && (bool)e.NewValue;
if (alwaysScrollToEnd) {
tb.ScrollToEnd();
tb.TextChanged += TextChanged;
} else {
tb.TextChanged -= TextChanged;
}
} else {
throw new InvalidOperationException("The attached AlwaysScrollToEnd property can only be applied to TextBox instances.");
}
}
public static bool GetAlwaysScrollToEnd(TextBox textBox)
{
if (textBox == null) {
throw new ArgumentNullException("textBox");
}
return (bool)textBox.GetValue(AlwaysScrollToEndProperty);
}
public static void SetAlwaysScrollToEnd(TextBox textBox, bool alwaysScrollToEnd)
{
if (textBox == null) {
throw new ArgumentNullException("textBox");
}
textBox.SetValue(AlwaysScrollToEndProperty, alwaysScrollToEnd);
}
private static void TextChanged(object sender, TextChangedEventArgs e)
{
((TextBox)sender).ScrollToEnd();
}
}
}
As far as I can tell, it behaves exactly as desired. Here's a test case with several text boxes in a window that allows the attached AlwaysScrollToEnd
property to be set in various ways (hard-coded, with a CheckBox.IsChecked
binding and in code-behind):
Xaml:
Code-Behind:
using System;
using System.Windows;
using System.Windows.Controls;
namespace AttachedPropertyTest
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
void Button_Click(object sender, RoutedEventArgs e)
{
TextBoxUtilities.SetAlwaysScrollToEnd(tb3, true);
}
}
}