18

I have several read only RichTextBox's that are used for logging output. Since they're read only they don't seem to automatically scroll when the text is updated. I can use the TextChanged event to force a scroll to end, but is there not simply a way to set a property or something in the XAML so that scrolling happens like normal?

Samuel Jack
  • 32,712
  • 16
  • 118
  • 155
Merad
  • 749
  • 1
  • 6
  • 14
  • possible duplicate of [Verticall scroll richtextbox on the bottom \[WPF\]](http://stackoverflow.com/questions/4256129/verticall-scroll-richtextbox-on-the-bottom-wpf) – Danny Beckett May 19 '15 at 23:08

5 Answers5

21

I had googled for your problem and found this post. In the section "Programming the RichTextBox" author had described about getting the behavior what you had been expecting.

Please check and let me know if it is of any use.


I tried to reproduce your problem and came up with the following solution

    <Window x:Class="CheckRichTextBox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="170" Width="300">
    <StackPanel>
        <RichTextBox Height="100" Name="richTextBox1" IsReadOnly="True" VerticalScrollBarVisibility="Visible"/>
        <Button Name="btnAdd" Content="Click me to add text" VerticalAlignment="Bottom" Click="BtnAddClick" />
    </StackPanel>
</Window>

The code behind for the same is as below:

using System.Windows;

namespace CheckRichTextBox
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void BtnAddClick(object sender, RoutedEventArgs e)
        {
            richTextBox1.AppendText("You had Clicked the button for adding text\n");
            richTextBox1.ScrollToEnd();
        }
    }
}

This solves the problem of autoscroll, please check it and let me know if it is of any help.

Pank
  • 670
  • 5
  • 12
18

I solved this problem using an Interactivity trigger and a very simple action.

The action looks like this:

public class ScrollToBottomAction : TriggerAction<RichTextBox>
{
    protected override void Invoke(object parameter)
    {
        AssociatedObject.ScrollToEnd();
    }
}

Then in my XAML I have this:

<RichTextBox IsReadOnly="True" VerticalScrollBarVisibility="Auto">
     <i:Interaction.Triggers>
            <i:EventTrigger EventName="TextChanged">
                <interactivity:ScrollToBottomAction/>
            </i:EventTrigger>
     </i:Interaction.Triggers>
</RichTextBox>
Samuel Jack
  • 32,712
  • 16
  • 118
  • 155
  • I cannot get this to work because of something to do with the blend version being old. And I've tried what was suggested in http://stackoverflow.com/questions/32024034/the-type-from-assembly-is-built-with-an-older-version-of-blend-sdk-and-is-not-su with no luck. Any thoughts? – Snoop Nov 16 '16 at 19:56
  • `` also works. – Dmitry S. Aug 24 '18 at 17:26
  • FYI - The `System.Windows.Interactivity` namespace is deprecated. Use `Microsoft.Xaml.Behaviors` instead, which includes the `TriggerAction` class. – Mike Bruno Mar 25 '22 at 16:56
2

I came up with the following solution for wpf richtextbox autoscroll

public partial class MainWindow
{
    private bool AutoScroll = true;

    public MainWindow()
    {
        InitializeComponent();

        yourRichTextBox.Loaded += (s, e) =>
          {
              var scrollViewer = VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(yourRichTextBox, 0), 0) as ScrollViewer;
              scrollViewer.ScrollChanged += (scroller, eScroller) => ScrollViewer_ScrollChanged(scroller, eScroller);
          };
    }

    private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        // User scroll event : set or unset autoscroll mode
        if (e.Source as ScrollViewer != null && e.ExtentHeightChange == 0)
        {   // Content unchanged : user scroll event
            if ((e.Source as ScrollViewer).VerticalOffset == (e.Source as ScrollViewer).ScrollableHeight)
            {   // Scroll bar is in bottom
                // Set autoscroll mode
                AutoScroll = true;
            }
            else
            {   // Scroll bar isn't in bottom
                // Unset autoscroll mode
                AutoScroll = false;
            }
        }

        // Content scroll event : autoscroll eventually
        if (AutoScroll && e.ExtentHeightChange != 0 && e.Source as ScrollViewer != null)
        {   // Content changed and autoscroll mode set
            // Autoscroll
            (e.Source as ScrollViewer).ScrollToVerticalOffset((e.Source as ScrollViewer).ExtentHeight);
        }
    }
}
0

This is how to do it in C#

Put the RichTextBox in a ScrollViewer like this:

scrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;

scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;

scrollViewer.Content = rTextBox;

Then add the scrollViewer to the Grid or whatever you are using.

RootGrid.Children.Add(scrollViewer);

(This is in C# but could all be done in XAML as well.)

Then use C# code like this to make it scroll to the bottom when you add text:

rTextBox.AppendText(str);
scrollViewer.ScrollToEnd();

Hope that helps.

-1
RichTextBox.AppendText("String")
RichTextBox.ScrollToCaret()

When I was adding to RichTextBox.text, ScrollToCaret() does not work.

RichTextBox.text = RichTextBox.text + "String"
RichTextBox.ScrollToCaret()
Community
  • 1
  • 1
  • 2
    `ScrollToCaret` is for a WinForms `RichTextBox`, not a WPF one. There's a question about that here: [Rich Text box scroll to the bottom when new data is written to it](http://stackoverflow.com/questions/9416608/rich-text-box-scroll-to-the-bottom-when-new-data-is-written-to-it) – Danny Beckett May 14 '15 at 01:07