我的RichTextBox
应用程序中有一个正在获取某些事件的新内容。
添加新内容时,我想滚动到底部,前提是之前滚动位于底部。
我该怎么做呢?
更具体地说,给我带来麻烦的部分是确定滚动位置。
如果重要的话,RichTextBox
使用默认样式和模板,一些画笔更改或设置为空,垂直滚动条可见性为自动并且它是只读的。
我的RichTextBox
应用程序中有一个正在获取某些事件的新内容。
添加新内容时,我想滚动到底部,前提是之前滚动位于底部。
我该怎么做呢?
更具体地说,给我带来麻烦的部分是确定滚动位置。
如果重要的话,RichTextBox
使用默认样式和模板,一些画笔更改或设置为空,垂直滚动条可见性为自动并且它是只读的。
如果您希望富文本框仅在滚动条被拖到底部时自动滚动新添加的文本,请将以下类添加到您的项目中
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();
}
}
然后在您想要自动滚动行为的任何富文本框上添加 IsAutoSroll 属性
<RichTextBox ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Auto" local:RichTextBoxThing.IsAutoScroll="True"/>
滚动更简单的条件是VerticalOffset + ViewportHeight >= ExtentHeight
例子:
bool shouldScroll = rtbx.VerticalOffset + rtbx.ViewportHeight >=
rtbx.ExtentHeight;
// changes to RichTextBox
// ...
if(shouldScroll) rtbx.ScrollToEnd();
也适用于“滚动条刚刚出现”的情况。
您基本上可以执行以下操作:获取滚动条,并订阅 , and 的更改Value
(Maximum
它们Minimum
都是依赖属性)。这样,您可以在需要时通过将 设置为Value
来控制代码隐藏中的位置Maximum
。
现在,您如何访问滚动条?有几种方法。如果您确定哪个是您的控制模板RichTextBox
,您可以使用它来获取它GetTemplateChild(name)
(您可以通过检查例如 Blend 中的模板来获取名称)。如果您不确定,您最好创建自己的模板(同样,Blend 会为您提供一个很好的开始模板)并将其应用于RichTextBox
您感兴趣的。
试试这个扩展方法:
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();
}
}
并像这样使用它:
textBox.AppendText(// Very long text here);
textBox.ScrollIfNeeded();
编辑:当滚动条变得可见时,包括滚动到底部的替代方法:
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();
}
}
}
}