繁体   English   中英

Silverlight 4 RichTextBox滚动到底部

[英]Silverlight 4 RichTextBox scroll to bottom

我正在使用Silverlight编写聊天应用程序。 我将内容动态添加到富文本框中,我需要向下滚动以显示最后的消息。 但是没有办法做到这一点。 我在互联网上找到的所有文档/代码都是旧的。

任何解决方案都会很乐意接受。

在我自己的应用程序中,我很长时间都在努力。 Dispatcher.BeginInvoke方法对我来说不可靠; 有时它会滚动到底部,有时则不会。 让它工作的唯一方法是在彼此内部嵌入两个Dispatcher.BeginInvoke调用,但我不喜欢这个解决方案。

我滥用事件处理程序,而不是使用Dispatcher。 在此示例中,只有在添加新内联时,文本框才会滚动到底部(聊天框的有用行为,允许用户在需要时阅读以前的消息)。 您可以将Run对象作为Inline参数传递。

private void AddInline(Inline inline)
{
    var viewer = textBox.GetChildByType<ScrollViewer>(item => item.Name == "ContentElement") as ScrollViewer;
    bool scrollToBottom = viewer.VerticalOffset == viewer.ScrollableHeight;

    // Creating the paragraph isn't necessary.
    // In my own application, I only add a single paragraph to the RichTextBox that displays my chat messages.
    // Then I just add new Inlines to the single paragraph.
    Paragraph p = new Paragraph();
    p.Inlines.Add(inline);

    if (scrollToBottom)
        textBox.LayoutUpdated += ScrollRichTextBoxToBottom;

    // Adding the paragraph triggers a layout update.
    // In the LayoutUpdated handler, the viewer will be scrolled to the bottom, triggering a second layout pass.
    textBox.Blocks.Add(p);
}

private void ScrollRichTextBoxToBottom(object sender, EventArgs e)
{
    // The LayoutUpdated handler needs to be removed, otherwise the RichTextBox becomes unscrollable.
    textBox.LayoutUpdated -= ScrollRichTextBoxToBottom;

    var viewer = textBox.GetChildByType<ScrollViewer>(item => item.Name == "ContentElement") as ScrollViewer;
    viewer.ScrollToVerticalOffset(viewer.ScrollableHeight);
}

注意:GetChildByType只是获取ScrollViewer的扩展方法。 (我没有创建这种扩展方法。)

public static class Extensions
{
    public static T GetChildByType<T>(this UIElement element, Func<T, bool> condition)
        where T : UIElement
    {
        List<T> results = new List<T>();
        GetChildrenByType<T>(element, condition, results);
        if (results.Count > 0)
            return results[0];
        else
            return null;
    }

    private static void GetChildrenByType<T>(UIElement element, Func<T, bool> condition, List<T> results)
        where T : UIElement
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
        {
            UIElement child = VisualTreeHelper.GetChild(element, i) as UIElement;
            if (child != null)
            {
                T t = child as T;
                if (t != null)
                {
                    if (condition == null)
                        results.Add(t);
                    else if (condition(t))
                        results.Add(t);
                }
                GetChildrenByType<T>(child, condition, results);
            }
        }
    }
}

您需要挖掘出作为RichTextBox模板一部分的ScrollViewer。 您可以借助一些基于VisualTreeHelper代码来完成此操作。 这里获取我的VisualTreeEnumeration类的代码。

现在,在项目中使用此类,您可以执行以下操作: -

ScrollViewer sv = rtb.Descendents().OfType<ScrollViewer>().FirstOrDefault();

完整的例子

创建一个新的应用程序并包含VisualTreeEnumeration类。

在MainPage.xaml中使用以下xaml: -

<Grid x:Name="LayoutRoot" Background="White">
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <RichTextBox x:Name="rtb" />
    <Button Content="Click Me" Click="Button_Click" Grid.Row="1" />
</Grid>

在它的代码背后添加这个: -

    int i = 0;
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Paragraph p = new Paragraph();
        p.Inlines.Add(new Run() { Text = "Hello " + (i++).ToString() });
        rtb.Blocks.Add(p);

        Dispatcher.BeginInvoke(() =>
        {
            ScrollViewer sv = rtb.Descendents().OfType<ScrollViewer>().FirstOrDefault();
            sv.ScrollToVerticalOffset(sv.ScrollableHeight);
            sv.UpdateLayout();
        });
    }

请注意使用BeginInvoke允许RTB在添加文本后自行排序。 使用BeginInvoke将UI线程调度程序上的其余代码排队。

好吧,你既不需要扩展方法也不需要调度程序。 将RichTexBox控件滚动到底部的最简单方法如下:

textBox.Selection.Select(textBox.ContentEnd,textBox.ContentEnd);

您可以以类似的方式实现“滚动到顶部”行为。

希望有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM