2009-10-31 25 views

cevap

7

Bir metin aralığı oluşturarak ve değişiklikler için izleyerek FlowDocument'daki değişiklikleri algılayabilirsiniz. Aşağıya kaydırma yapmak daha zor çünkü ScrollViewer'u bulmanız gerekiyor. Ayrıca performans için, tüm değişikliklerde tüm kaydırma hesaplarını yeniden yapmak istemezsiniz, bu yüzden DispatcherOperations'u kullanmalısınız. FindFirstVisualDescendantOfType Belirtilen bulundu basit bir derinlik ilk önek VisualTreeHelper.GetChildrenCount() ve VisualTreeHelper.GetChild() kullanılarak görsel ağacının arama ve birinci Görsel dönen olduğunu

var range = new TextRange(flowDocument.ContentStart, flowDocument.ContentEnd); 
object operation = null; 

range.Changed += (obj, e) => 
{ 
    if(operation==null) 
    operation = Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() => 
    { 
     operation = null; 

     var scrollViewer = FindFirstVisualDescendantOfType<ScrollViewer>(flowDocument); 
     scrollViewer.ScrollToBottom(); 
    }); 
}; 

: bu kod hile yapmak gerekir Hepsini bir araya getirirsek

yazın.

Tam genellik için, FlowDocumentScrollViewer'un şablonu değişebileceğinden, kodun üst kısmındaki scrollViewer'ı önceden çalıştırmamaya dikkat edin. Bu olmayacak, bu kod FlowDocumentScrollViewer üzerinde .ApplyTemplate() arayarak ve ardından olay işleyicisi kayıtlı önce scrollViewer hesaplayarak hızlandırılabiliyorsa: biz sadece scrollViewer.GetTemplateChild("PART_ContentHost") arayıp görsel ağaç araması atlayamazsınız

var range = new TextRange(flowDocument.ContentStart, flowDocument.ContentEnd); 
object operation = null; 

flowDocument.ApplyTemplate(); 
var scrollViewer = FindFirstVisualDescendantOfType<ScrollViewer>(flowDocument); 

range.Changed += (obj, e) => 
{ 
    if(operation==null) 
    operation = Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() => 
    { 
     operation = null; 
     scrollViewer.ScrollToBottom(); 
    }); 
}; 

Not Çünkü GetTemplateChild korunmaktadır.

+0

FlowDocument ve FlowDocumentScrollViewer görsel ağaç koduyla bunlardan hiçbirine ihtiyacım yoktu. Sadece 2 Invokes, 1 paragrafı oluşturmak ve eklemek için 1 ve 1 paragrafları ekleyin. –

2

bir TextChanged Etkinliğe çengel sonra, basitçe kullanabilirsiniz: Bu sayfalarda (a FlowDocumentPageViewer, üzerinde ve aynı zamanda bir FlowDocumentReader üzerinde sadece çalışır

// Showing Last Block 
YourReader.Document.Blocks.LastBlock.BringIntoView(); 

// Or.. showing the last Inline 
(YourReader.Document.Blocks.LastBlock as Paragraph).Inlines.LastInline.BringIntoView(); 

Ama Bir FlowDocumentScrollViewer için ViewingModes), görsel ağacı şu şekilde kullanmalısınız

public static ScrollViewer FindScroll(Visual visual) 
     { 
      if (visual is ScrollViewer) 
       return visual as ScrollViewer; 

      ScrollViewer searchChiled = null; 
      DependencyObject chiled; 

      for (int i = 0; i < VisualTreeHelper.GetChildrenCount(visual); i++) 
      { 
       chiled = VisualTreeHelper.GetChild(visual, i); 
       if (chiled is Visual) 
        searchChiled = FindScroll(chiled as Visual); 
       if (searchChiled != null) 
        return searchChiled; 
      } 

      return null; 
     } 

ScrollViewer scroller = FindScroll(YourReader as Visual); 
if (scroller != null) 
    (scroller as ScrollViewer).ScrollToBottom(); 
+0

Sadece bir FlowDocument ve FlowDocumentscrollViewer kullanıyorum.Yukarıdaki BringIntoView çözümü benim için mükemmel çalışıyor. VisualTreeHelper 'a ihtiyacım olmadı Çözümüm paragrafı oluşturmak için Dispatcher.Invoke kullanmak, bu paragrafı bir değişken olarak saklamak ve daha sonra Dispatcher.Invoke'u yeniden görüntüye getirmek için kullanmaktır. Bu en basit yöntem gibi görünüyor. –

0

Sen iç kaydırma görüntüleyici almak için aşağıdaki uzatma yöntemi kullanabilirsiniz:

public static class FlowDocumentScrollViewerExtensions 
{ 
    public static ScrollViewer GetScrollViewer(this FlowDocumentScrollViewer element) { 
    if (element == null) { 
     throw new ArgumentNullException(nameof(element)); 
    } 

    return element.Template?.FindName("PART_ContentHost", element) as ScrollViewer; 
    } 
} 

Ayrıca size kaydırmak istediğiniz durumda (kaydırma konumunu belirlemeye ScrollViewer kendisi kontrol etmek içerik eklemeden önce bu uzatma yöntemleri kullanabilirsiniz - kaydırma izleyici örneğin son) zaten olsaydı sadece-:

public static class ScrollViewerExtensions 
{ 
    public static bool IsAtHome(this ScrollViewer element) { 
    if (element == null) { 
     throw new ArgumentNullException(nameof(element)); 
    } 

    return element.VerticalOffset <= 0; 
    } 

    public static bool IsAtEnd(this ScrollViewer element) { 
    if (element == null) { 
     throw new ArgumentNullException(nameof(element)); 
    } 

    return element.VerticalOffset >= element.ScrollableHeight; 
    } 
} 

Daha sonra sadece örneğin scrollViewer.ScrollToEnd() diyoruz.