2016-07-19 15 views
0

Ich habe zwei FlowDocuments Seite an Seite in zwei verschiedenen Stack Panels. Ich brauche eine Möglichkeit, beide Dokumente gleichzeitig nach einem bestimmten Text zu durchsuchen. Wie in, wenn ich "Auto" in das Textfeld eintippe, sollten beide Flussdokumentleser nach der nächsten Instanz von "Auto" suchen und scrollen, wenn es eine gibt. Gibt es einen Weg, dies zu erreichen? Das FlowDocument befindet sich in einem FlowDocumentReader.Sie können zwei FlowDocuments gleichzeitig durchsuchen?

Antwort

3

Hier habe ich eine grundlegende WPF XAML-Layout, mit 2 FlowDocumentReader wie Sie angegeben. Ich habe eine TextBox suchen und werde den Code hinter ausgeführt, wenn die Suchtextänderungen:

<Window x:Class="WpfFlowTest.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:WpfFlowTest" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525"> 

    <DockPanel> 
    <!-- Search Box --> 
    <TextBox Name="SearchTextBox" DockPanel.Dock="Top" TextChanged="TextBox_TextChanged"/> 

    <!-- 2 Flow Readers --> 
    <UniformGrid Columns="2"> 
     <FlowDocumentReader Name="FlowReader1"> 
     <FlowDocument> 
      <Paragraph> 
      Here is some text in panel number 1 
      </Paragraph> 
     </FlowDocument> 
     </FlowDocumentReader> 

     <FlowDocumentReader Name="FlowReader2"> 
     <FlowDocument> 
      <Paragraph> 
      Here is some more text in panel number 2 
      </Paragraph> 
     </FlowDocument> 
     </FlowDocumentReader> 
    </UniformGrid> 
    </DockPanel> 
</Window> 

In den MainWindow.xaml.cs Datei ich diesen Code haben, die den Fluss Dokument markieren, wo der Text, was passt Sie eingegeben:

private void TextBox_TextChanged(object sender, TextChangedEventArgs e) 
     { 
      var searchText = SearchTextBox.Text; 

      DoSearch(FlowReader1, searchText); 
      DoSearch(FlowReader2, searchText); 
     } 

     private void DoSearch(FlowDocumentReader reader, string search) 
     { 
      var doc = reader.Document; 
      var text = doc.ContentStart; 

      var docRange = new TextRange(doc.ContentStart, doc.ContentEnd); 
      docRange.ClearAllProperties(); 

      while (true) 
      { 
       var next = text.GetNextContextPosition(LogicalDirection.Forward); 
       if (next == null) 
       { 
        break; 
       } 

       var txt = new TextRange(text, next); 

       int indx = txt.Text.IndexOf(search); 
       if (indx > 0) 
       { 
        var sta = text.GetPositionAtOffset(indx); 
        var end = text.GetPositionAtOffset(indx + search.Length); 
        var textR = new TextRange(sta, end); 

        // Make it yellow 
        textR.ApplyPropertyValue(TextElement.BackgroundProperty, new SolidColorBrush(Colors.Yellow)); 
       } 
       text = next; 
      } 

     } 
+0

Das ist eine ziemlich gute Lösung. – jailorboy

+0

Gibt es eine Möglichkeit, das Dokument zum markierten Text zu scrollen? – jailorboy

+0

Nach meinem Wissen gibt es keine eingebaute Möglichkeit, das Dokument zum markierten Text zu scrollen, aber Sie können es selbst berechnen, wenn Sie die 'LineHeight',' PagePadding' und andere Abstände oder Ränder (wie Abstände) kennen zwischen Absätzen) in Ihrem Dokument. – Meloviz

0

ich habe meine leichte Modifikation für Menschen geschrieben, die blättern wollen.

private void TextBox_TextChanged(object sender, EventArgs e) 
     { 
      var searchText = SearchTextBox.Text; 

      if (searchText != null || searchText != "") 
      { 
       var FlowReader1 = (FlowDocumentReader)diffResults.Children[0]; 
       var FlowReader2 = (FlowDocumentReader)oldResults.Children[0]; 

       DoSearch(FlowReader1, searchText); 
       DoSearch(FlowReader2, searchText); 
      } 
     } 

     private void DoSearch(FlowDocumentReader reader, string search) 
     { 
      bool toScroll = true; 
      var doc = reader.Document; 
      var text = doc.ContentStart; 

      var docRange = new TextRange(doc.ContentStart, doc.ContentEnd); 
      docRange.ClearAllProperties(); 

      while (true) 
      { 
       var next = text.GetNextContextPosition(LogicalDirection.Forward); 
       if (next == null) 
       { 
        break; 
       } 

       var txt = new TextRange(text, next); 

       int indx = txt.Text.IndexOf(search); 
       if (indx >= 0) 
       { 
        var sta = text.GetPositionAtOffset(indx); 
        var end = text.GetPositionAtOffset(indx + search.Length); 
        if (end == null) 
        { 
         end = text.GetPositionAtOffset(indx + 1); 
        } 
        var textR = new TextRange(sta, end); 

        if (toScroll && text.Paragraph != null) 
        { 
         text.Paragraph.BringIntoView(); 
         toScroll = false; 
        } 
        // Make it yellow 
        textR.ApplyPropertyValue(TextElement.BackgroundProperty, new SolidColorBrush(Colors.Yellow)); 
       } 
       text = next; 
      } 
+0

Während 'BringIntoView()' es tatsächlich in den 'Viewport' bringt, bringt es es nicht notwendigerweise zu einer voreingestellten Position im' Viewport', was ich denke, was Sie gesucht haben, tut mir leid. Ich nahm an, du wolltest es ganz oben auf dem "Viewport", also ist das mein Fehler. Aber wenn du den Text an die Spitze des Ganzen bringen willst, es sei denn, es gibt etwas da draußen, das ich nicht kenne, müsstest du es tatsächlich berechnen. Das musste ich tun. – Meloviz

+0

Ja, ich wollte nur sicherstellen, dass es für den Benutzer sichtbar ist. – jailorboy

Verwandte Themen