我的应用程序中有一个RichTextBox
,它在某些事件上获取新内容。
添加新内容时,如果滚动在底部之前,我想滚动到底部,。
我该怎么做?
更具体地说,给我麻烦的部分是确定滚动位置。WPF RichTextBox的有条件滚动?
如果很重要,RichTextBox
正在使用默认样式和模板,几个画笔已更改或设置为空,垂直滚动条可见性为自动且为只读。
我的应用程序中有一个RichTextBox
,它在某些事件上获取新内容。
添加新内容时,如果滚动在底部之前,我想滚动到底部,。
我该怎么做?
更具体地说,给我麻烦的部分是确定滚动位置。WPF 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"/>
基本上可以做到以下几点:获取滚动条,并订阅Value
,Maximum
和Minimum
(它们都是依赖项属性)的更改。通过这种方式,您可以通过在需要时将Value
设置为Maximum
来控制代码隐藏的位置。
现在,你如何访问滚动条?有几种方法。如果您确定哪一个是您的RichTextBox
的控件模板,您可以使用GetTemplateChild(name)
(您通过检查例如Blend中的模板来获得名称)。如果你不确定,你应该更好地创建自己的模板(再次,Blend会给你一个很好的模板开始),并将其应用到你感兴趣的RichTextBox
。
试试这个扩展m ethod:
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();
}
}
}
}
简单多条件滚动VerticalOffset + ViewportHeight >= ExtentHeight
示例:
bool shouldScroll = rtbx.VerticalOffset + rtbx.ViewportHeight >=
rtbx.ExtentHeight;
// changes to RichTextBox
// ...
if(shouldScroll) rtbx.ScrollToEnd();
也适用于'滚动条刚出现'的情况。
这个效果很好,但由于您比较可能相等的双倍数,所以您应该在比较中引入一个“epsilon”。基本上我做了'rtbx.VerticalOffset + rtbx.ViewportHeight> = rtbx.ExtentHeight - 1.0;'它运作良好。我仍然投票,因为这节省了我一些时间! – Benlitz
您可以将VerticalOffset与ViewportHeight进行比较吗? – Paparazzi