【问题标题】:Any way to search two FlowDocuments at the same time?有什么方法可以同时搜索两个 FlowDocuments?
【发布时间】:2016-07-19 19:47:09
【问题描述】:

我在两个不同的堆栈面板中并排有两个 FlowDocument。我需要一种同时在两个文档中搜索特定文本的方法。就像我在文本框中键入“汽车”一样,流文档阅读器都应该搜索并滚动到“汽车”的下一个实例(如果有的话)。有没有办法实现这一目标? FlowDocument 位于 FlowDocumentReader 中。

【问题讨论】:

    标签: c# .net wpf user-interface flowdocument


    【解决方案1】:

    这里我有一个基本的 WPF XAML 布局,其中包含您指定的 2 个 FlowDocumentReader。我有一个搜索文本框,只要搜索文本发生变化,我就会运行后面的代码:

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

    在 MainWindow.xaml.cs 文件中,我有这段代码,它将突出显示文本与您输入的内容匹配的流文档:

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

    【讨论】:

    • 有没有办法将文档滚动到突出显示的文本?
    • 据我所知,没有内置方法可以将文档滚动到突出显示的文本,但如果您知道LineHeightPagePadding 和任何文档中的其他填充或边距(如段落之间的间距)。
    • 我希望有一种方法可以使用 BringIntoView() 方法来滚动文档。
    • 我已经为想要滚动的人发布了我的轻微修改。
    • 我的 FlowDocument 包含一个表格,出于某种原因,每当我在最后一行搜索任何内容时,sta 和/或 end 总是为空。
    【解决方案2】:

    我已经为想要滚动的人发布了我的轻微修改。

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

    【讨论】:

    • 虽然BringIntoView() 确实将它带入了Viewport,但它并不一定将它带到Viewport 中的任何预设位置,我猜这就是您要找的,抱歉.我只是假设你想要它在Viewport 的顶部,所以那是我的错。但是如果你想把文本放在它的最顶端,除非有什么我不知道的,你实际上必须计算它。这就是我必须做的。
    • 是的,我只是想确保它对用户可见。
    猜你喜欢
    • 1970-01-01
    • 2013-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-08
    • 2014-12-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多