2009-10-31 15 views
5

मैं पता लगाने के लिए (अधिमानतः एक घटना के माध्यम से) जब किसी भी सामग्री को जोड़ दिया जाता है चाहता हूँ, एक FlowDocument में बदल गया है, आदि और मैं अपने आप को समाप्त करने के लिए स्क्रॉल करने FlowDocument को दिखाती हुई एक FlowDocumentScrollViewer पैदा करने के लिए चाहते हैं जब यह होता है ।का पता लगाने FlowDocument बदलें और स्क्रॉल

उत्तर

7

आप पाठ श्रेणी बनाकर और परिवर्तनों के लिए निगरानी करके FlowDocument में परिवर्तनों का पता लगा सकते हैं। नीचे स्क्रॉल करना अधिक कठिन है क्योंकि आपको ScrollViewer मिलना है। प्रदर्शन के लिए आप प्रत्येक परिवर्तन पर सभी स्क्रॉलिंग गणना को फिर से नहीं चाहते हैं, इसलिए आपको DispatcherOperations का उपयोग करना चाहिए।

यह सब एक साथ रखें, इस कोड चाल करना चाहिए:

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

जहां FindFirstVisualDescendantOfType दृश्य पेड़ VisualTreeHelper.GetChildrenCount() और VisualTreeHelper.GetChild() का उपयोग करने का एक सरल गहराई-प्रथम उपसर्ग खोज और पहले दृश्य लौटने निर्दिष्ट की पाया है प्रकार।

ध्यान दें कि पूर्ण सामान्यता के लिए मैं कोड के शीर्ष पर scrollViewer का प्रीकंपूट नहीं करता क्योंकि FlowDocumentScrollViewer का टेम्पलेट बदल सकता है। अगर यह नहीं होगा, इस कोड FlowDocumentScrollViewer पर .ApplyTemplate() बुला और फिर कंप्यूटिंग scrollViewer से पहले ईवेंट हैंडलर पंजीकृत किया गया है द्वारा को गति जा सकता है:

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

ध्यान दें कि हम केवल scrollViewer.GetTemplateChild("PART_ContentHost") फोन नहीं कर सकते हैं और दृश्य पेड़ खोज को छोड़ क्योंकि GetTemplateChild संरक्षित है।

+0

मुझे FlowDocument और FlowDocumentScrollViewer दृश्य पेड़ कोड के साथ इनमें से किसी की आवश्यकता नहीं थी। केवल 2 Invokes, 1 स्ट्रिंग से पैराग्राफ बनाने और जोड़ने के लिए 1 और उस अनुच्छेद को देखने के लिए 1। –

2

क्या आप संपादन करने के लिए RichTextBox का उपयोग कर रहे हैं? यदि ऐसा है तो आपको the TextChanged event को हुक करने में सक्षम होना चाहिए और फिर पर the ViewportHeight property के मान के साथ कॉल करना चाहिए।

+0

नहीं FlowDocumentScrollViewer का उपयोग, RichTextBox नहीं। –

2

एक TextChanged घटना के लिए ऊपर hooking के बाद, आप बस का उपयोग कर सकते हैं:

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

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

लेकिन, यह एक FlowDocumentPageViewer, पर और यह भी एक FlowDocumentReader पर काम करता है केवल (पृष्ठों के साथ ViewingModes), FlowDocumentScrollViewer के लिए आपको दृश्य पेड़ का उपयोग करना चाहिए जैसा कि

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

मैं केवल एक फ्लो डॉक्यूमेंट और फ़्लो डॉक्यूमेंट्सक्रॉल व्यूअर का उपयोग कर रहा हूं।ऊपर BringIntoView समाधान मेरे लिए पूरी तरह से काम करता है। मुझे VisualTreeHelper मेरा समाधान डिस्पैचर का उपयोग करना है। पैराग्राफ बनाने के लिए इन्वोक, उस अनुच्छेद को एक चर के रूप में संग्रहीत करें और फिर डिस्पैचर। इसे फिर से देखने के लिए फिर से जुड़ें। यह सबसे आसान तरीका प्रतीत होता है। –

0

आप आंतरिक स्क्रॉल दर्शक पाने के लिए निम्न एक्सटेंशन विधि का उपयोग कर सकते हैं:

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

इसके अतिरिक्त आप (स्क्रॉल स्थिति ScrollViewer खुद जांच करने के लिए आप स्क्रॉल करना चाहते मामले में सामग्री जोड़ने से पहले इन विस्तार तरीकों का उपयोग कर सकते हैं - केवल- यदि पुस्तक दर्शक उदाहरण के लिए अंत) पर पहले से ही था:

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

बाद में सिर्फ scrollViewer.ScrollToEnd() उदाहरण के लिए कहते हैं।

संबंधित मुद्दे