具有自动垂直滚动的多行文本框

Jad*_*ded 41 wpf textbox multiline autoscroll

在互联网上有许多类似的问题,包括SO,但提议的解决方案在我的情况下不起作用.场景:xaml中有一个日志文本框

 <TextBox Name="Status"
          Margin="5"
          Grid.Column="1"
          Grid.Row="5"
          HorizontalAlignment="Left"
          VerticalAlignment="Top"
          Width="600"
          Height="310"/>
Run Code Online (Sandbox Code Playgroud)

在代码隐藏中有一些方法可以做一些工作并在这个文本框中添加一些多行(可能就是问题?)消息:

private static void DoSomeThings(TextBox textBox)
{
   // do work
   textBox.AppendText("Work finished\r\n"); // better way than Text += according to msdn
   // do more
   textBox.AppendText("One more message\r\n");
   ...
}

private static void DoSomething2(TextBox textBox)
{
   // same as first method
}
Run Code Online (Sandbox Code Playgroud)

执行所有操作后,需要滚动到文本框的底部.尝试ScrollToEnd(),ScrollToLine,将文本框包装到ScrollViewer,Selection和Caret解决方法,将ScrollToEnd附加到TextChanged.在溢出文本框高度的执行行仍然需要手动滚动之后,这些都不起作用.对不起重复的问题,我想我错过了一些小问题,可以由对问题有新见解的人迅速解决.提前致谢.

Adr*_*ciu 81

根据这个问题:TextBox.ScrollToEnd在TextBox处于非活动选项卡时不起作用

您必须聚焦文本框,更新插入位置,然后滚动到结束:

Status.Focus();
Status.CaretIndex = Status.Text.Length;
Status.ScrollToEnd();
Run Code Online (Sandbox Code Playgroud)

编辑

示例TextBox:

<TextBox TextWrapping="Wrap" VerticalScrollBarVisibility="Auto" 
         AcceptsReturn="True" Name="textBox"/>
Run Code Online (Sandbox Code Playgroud)


小智 17

如果你把它变成一个简单的自定义控件,那么你不需要任何代码来进行滚动.

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();
    }

}
Run Code Online (Sandbox Code Playgroud)

如果你正在使用WPF,那么使用绑定会好得多,而不是在后面的代码中传递文本框.

  • +1比起同一主题上的其他帖子要简单得多,我什至只保留了OnTextChanged(...){base.OnTextChanged(e); ScrollToEnd();},因为对于我的简单应用程序而言,这已经足够了。 (2认同)

yan*_*ich 11

如果您不太喜欢背后的代码,这里有一个可以解决问题的 AttachedProperty:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在您的 xaml 中执行以下操作:

<TextBox
    AcceptsReturn="True"
    myAttachedProperties:TextBoxAttachedProperties.AutoScrollToEnd="True"/>
Run Code Online (Sandbox Code Playgroud)

只是不要忘记在 xaml 文件的顶部添加

xmlns:myAttachedProperties="clr-namespace:YourProject.YourAttachedProperties"
Run Code Online (Sandbox Code Playgroud)