簡體   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