Multiline Textbox with automatic vertical scroll

后端 未结 4 1410
清酒与你
清酒与你 2020-12-14 05:37

There are a lot of similiar questions over internet, on SO included, but proposed solutions doesn\'t work in my case. Scenario : there is a log textbox in xaml



        
相关标签:
4条回答
  • 2020-12-14 06:13

    If you don't like code behind to much, here is an AttachedProperty that will do the trick :

    namespace YourProject.YourAttachedProperties
    {
    
        public class TextBoxAttachedProperties
        {
    
            public static bool GetAutoScrollToEnd(DependencyObject obj)
            {
                return (bool)obj.GetValue(AutoScrollToEndProperty);
            }
    
            public static void SetAutoScrollToEnd(DependencyObject obj, bool value)
            {
                obj.SetValue(AutoScrollToEndProperty, value);
            }
    
            // Using a DependencyProperty as the backing store for AutoScrollToEnd.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty AutoScrollToEndProperty =
            DependencyProperty.RegisterAttached("AutoScrollToEnd", typeof(bool), typeof(TextBoxAttachedProperties), new PropertyMetadata(false, AutoScrollToEndPropertyChanged));
    
            private static void AutoScrollToEndPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                if(d is TextBox textbox && e.NewValue is bool mustAutoScroll && mustAutoScroll)
                {
                    textbox.TextChanged += (s, ee)=> AutoScrollToEnd(s, ee, textbox);
                }
            }
    
            private static void AutoScrollToEnd(object sender, TextChangedEventArgs e, TextBox textbox)
            {
                textbox.ScrollToEnd();
            }
        }
    }
    

    And then in your xaml just do :

    <TextBox
        AcceptsReturn="True"
        myAttachedProperties:TextBoxAttachedProperties.AutoScrollToEnd="True"/>
    

    Just don't forget to add at the top of your xaml file

    xmlns:myAttachedProperties="clr-namespace:YourProject.YourAttachedProperties"
    

    And voila

    0 讨论(0)
  • 2020-12-14 06:21

    If you make it into a simple custom control then you don't need any code behind to do the scrolling.

    public class ScrollingTextBox : TextBox {
    
        protected override void OnInitialized (EventArgs e) {
            base.OnInitialized(e);
            VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
            HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
        }
    
        protected override void OnTextChanged (TextChangedEventArgs e) {
            base.OnTextChanged(e);
            CaretIndex = Text.Length;
            ScrollToEnd();
        }
    
    }
    

    If you're using WPF it would be far better to use binding rather than passing the text box around in the code behind.

    0 讨论(0)
  • 2020-12-14 06:27

    Thanks! I have added this to remember the original focus:

    var oldFocusedElement = FocusManager.GetFocusedElement(this);
    
    this.textBox.Focus();
    this.textBox.CaretIndex = this.textBox.Text.Length;
    this.textBox.ScrollToEnd();
    
    FocusManager.SetFocusedElement(this, oldFocusedElement);
    
    0 讨论(0)
  • 2020-12-14 06:32

    According to this question: TextBox.ScrollToEnd doesn't work when the TextBox is in a non-active tab

    You have to focus the text box, update the caret position and then scroll to end:

    Status.Focus();
    Status.CaretIndex = Status.Text.Length;
    Status.ScrollToEnd();
    

    EDIT

    Example TextBox:

    <TextBox TextWrapping="Wrap" VerticalScrollBarVisibility="Auto" 
             AcceptsReturn="True" Name="textBox"/>
    
    0 讨论(0)
提交回复
热议问题