WPF RichTextBox有条件滚动?

时间:2012-11-19 15:03:54

标签: wpf richtextbox

我的应用中有一个RichTextBox,可以获得某些活动的新内容 添加新内容后,我想滚动到底部,仅当滚动位于之前的时才
我该怎么办?
更具体地说,给我带来麻烦的部分是确定滚动位置。

如果重要,RichTextBox正在使用默认样式和模板,一些画笔已更改或设置为null,垂直滚动条可见性为自动且它是只读的。

4 个答案:

答案 0 :(得分:3)

如果您希望富文本框仅在滚动条拖动到底部时使用新添加的文本自动滚动,请将以下类添加到项目中

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"/> 

答案 1 :(得分:3)

更简单的滚动条件是VerticalOffset + ViewportHeight >= ExtentHeight

示例:

bool shouldScroll = rtbx.VerticalOffset + rtbx.ViewportHeight >= 
                    rtbx.ExtentHeight;

// changes to RichTextBox 
// ...

if(shouldScroll) rtbx.ScrollToEnd();

也适用于'滚动栏刚出现'的情况。

答案 2 :(得分:1)

您基本上可以执行以下操作:获取滚动条,并订阅ValueMaximumMinimum的更改(它们都是依赖项属性)。这样,您可以在需要时将Value设置为Maximum来控制代码隐藏中的位置。

现在,您如何访问滚动条?有几种方法。如果您确定哪个是RichTextBox的控件模板,则可以使用GetTemplateChild(name)获取该模板(您可以通过检查例如Blend中的模板获取名称)。如果你不确定,你应该更好地创建自己的模板(再次,Blend会给你一个很好的模板开始)并将它应用到你感兴趣的RichTextBox

答案 3 :(得分:0)

试试这个扩展方法:

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