WPF RichTextBox conditionally scrolls?

I have a RichTextBox in my application that receives new content for certain events.
When new content is added, I would like to scroll down , only if the scroll was down to .
How to do it?
More specifically, the part that causes me problems determines the scroll position.

If this is important, RichTextBox uses the default style and template, several brushes are changed or set to zero, the visibility of the vertical scrollbar is Auto and it is read-only.

+4
source share
4 answers

If you want the expanded text to automatically scroll with the newly added text only when the scroll bar has been dragged down, add the following class to your project

 public class RichTextBoxThing : DependencyObject { public static bool GetIsAutoScroll(DependencyObject obj) { return (bool)obj.GetValue(IsAutoScrollProperty); } public static void SetIsAutoScroll(DependencyObject obj, bool value) { obj.SetValue(IsAutoScrollProperty, value); } public static readonly DependencyProperty IsAutoScrollProperty = DependencyProperty.RegisterAttached("IsAutoScroll", typeof(bool), typeof(RichTextBoxThing), new PropertyMetadata(false, new PropertyChangedCallback((s, e) => { RichTextBox richTextBox = s as RichTextBox; if (richTextBox != null) { if ((bool)e.NewValue) richTextBox.TextChanged += richTextBox_TextChanged; else if ((bool)e.OldValue) richTextBox.TextChanged -= richTextBox_TextChanged; } }))); static void richTextBox_TextChanged(object sender, TextChangedEventArgs e) { RichTextBox richTextBox = sender as RichTextBox; if ((richTextBox.VerticalOffset + richTextBox.ViewportHeight) == richTextBox.ExtentHeight || richTextBox.ExtentHeight < richTextBox.ViewportHeight) richTextBox.ScrollToEnd(); } } 

then in any rich text field that you want the auto-scroll behavior to add the IsAutoSroll property

 <RichTextBox ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Auto" local:RichTextBoxThing.IsAutoScroll="True"/> 
+3
source

A simpler scroll condition: VerticalOffset + ViewportHeight >= ExtentHeight

Example:

 bool shouldScroll = rtbx.VerticalOffset + rtbx.ViewportHeight >= rtbx.ExtentHeight; // changes to RichTextBox // ... if(shouldScroll) rtbx.ScrollToEnd(); 

Also works for scrolling.

+3
source

Basically, you can do the following: get the scroll bar and subscribe to the changes of Value , Maximum and Minimum (all of them are dependent properties). This way you can control the position in the code by setting Value to Maximum when you need to.

Now, how can you access the scrollbar? There are several ways. If you are sure that this is the control template for your RichTextBox , you can get it using GetTemplateChild(name) (you will get the name by examining the template, for example Blend). If you're not sure, you better create your own template (again, Blend will give you a good template to start with) and apply it to the RichTextBox that interests you.

+1
source

Try using this extension method:

 public static class RichTextBoxExtensions { public static void ScrollIfNeeded(this RichTextBox textBox) { var offset = textBox.VerticalOffset + textBox.ViewportHeight; if (Math.Abs(offset - textBox.ExtentHeight) > double.Epsilon) return; textBox.ScrollToEnd(); } } 

And use it as follows:

 textBox.AppendText(// Very long text here); textBox.ScrollIfNeeded(); 

EDIT : An alternative involving scrolling down when the scroll bar becomes visible:

 public static class RichTextBoxExtensions { public static void ScrollIfNeeded(this RichTextBox textBox) { var offset = textBox.VerticalOffset + textBox.ViewportHeight; if (Math.Abs(offset - textBox.ExtentHeight) <= double.Epsilon) { textBox.ScrollToEnd(); } else { var contentIsLargerThatViewport = textBox.ExtentHeight > textBox.ViewportHeight; if (Math.Abs(textBox.VerticalOffset - 0) < double.Epsilon && contentIsLargerThatViewport) { textBox.ScrollToEnd(); } } } } 
0
source

Source: https://habr.com/ru/post/1446983/


All Articles