2012-11-19 41 views
4

我的應用程序中有一個RichTextBox,它在某些事件上獲取新內容。
添加新內容時,如果滾動在底部之前,我想滾動到底部,
我該怎麼做?
更具體地說,給我麻煩的部分是確定滾動位置。
WPF RichTextBox的有條件滾動?

如果很重要,RichTextBox正在使用默認樣式和模板,幾個畫筆已更改或設置爲空,垂直滾動條可見性爲自動且爲只讀。

+0

您可以將VerticalOffset與ViewportHeight進行比較嗎? – Paparazzi

回答

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

與其他答案相同。滾動條剛出現時不起作用。 – Vercas

+0

我已編輯好照顧啓動案例 – Andy

+0

謝謝!它的工作原理與我現在所期望的完全相同。我比其他人更喜歡這個解決方案,因爲它也給了我一個使用附加屬性的例子,並展示了我稍後可以使用的這個控件的一些屬性。我以前不知道該找什麼。 – Vercas

1

基本上可以做到以下幾點:獲取滾動條,並訂閱Value,MaximumMinimum(它們都是依賴項屬性)的更改。通過這種方式,您可以通過在需要時將Value設置爲Maximum來控制代碼隱藏的位置。

現在,你如何訪問滾動條?有幾種方法。如果您確定哪一個是您的RichTextBox的控件模板,您可以使用GetTemplateChild(name)(您通過檢查例如Blend中的模板來獲得名稱)。如果你不確定,你應該更好地創建自己的模板(再次,Blend會給你一個很好的模板開始),並將其應用到你感興趣的RichTextBox

0

試試這個擴展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(); 
      } 
     } 
    } 
} 
+0

在滾動條可見之前它不起作用。(在內容大於可用空間之前) – Vercas

+0

不,因爲在滾動條可見之前,「VerticalOffset」是0.你說你只希望它滾動到底部,如果它已經在底部... – khellang

+0

@Vercas查看修訂後的答案... – khellang

3

簡單多條件滾動VerticalOffset + ViewportHeight >= ExtentHeight

示例:

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

// changes to RichTextBox 
// ... 

if(shouldScroll) rtbx.ScrollToEnd(); 

也適用於'滾動條剛出現'的情況。

+0

這個效果很好,但由於您比較可能相等的雙倍數,所以您應該在比較中引入一個「epsilon」。基本上我做了'rtbx.VerticalOffset + rtbx.ViewportHeight> = rtbx.ExtentHeight - 1.0;'它運作良好。我仍然投票,因爲這節省了我一些時間! – Benlitz