首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >FlowDocumentPageViewer SearchText和高亮显示

FlowDocumentPageViewer SearchText和高亮显示
EN

Stack Overflow用户
提问于 2009-11-18 13:52:43
回答 2查看 860关注 0票数 0

我正在创建一个搜索,并使用FlowDocumentPageViewer突出显示文本,类似于给定的链接。

http://kentb.blogspot.com/2009/06/search-and-highlight-text-in-arbitrary.html

当我搜索字符串的标记时,(使用字符串列表)一切都很好,并且我的矩形也得到了适当的应用。但我有两个问题

  1. 当我更改FlowDocumentPageViewer的页面时,我的矩形高亮区域保持不变,并且不会随着文本下沉。
  2. 当我放大或缩小FlowDocumentPageViewer时,文本会被放大,但是突出显示的矩形保持在相同的位置,

请您帮助我解决这个问题,以便将矩形应用到文本本身。我在这里提出申请。如果你还需要更多的信息,请告诉我。

代码语言:javascript
运行
复制
    <StackPanel Grid.Row="0" Orientation="Horizontal">
        <TextBox x:Name="_searchTextBox" Text="{Binding SearchText, UpdateSourceTrigger=PropertyChanged}" Width="200" Height="20" Margin="2"/>
        <Button x:Name="_searchButton" Height="{Binding Height, ElementName=_searchTextBox}" Width="50" Content="GO">
            </Button>
            <Button x:Name="_listItems" Height="{Binding Height, ElementName=_searchTextBox}" Width="50" Content="List"/>
        </StackPanel>

    <Grid Grid.Row="1">
        <FlowDocumentPageViewer>
            <FlowDocument Foreground="Black" FontFamily="Arial">
                <Paragraph FontSize="11">
                    The following details have been details from Amazon to match your initial query.Some of the returned values may have been empty, so have been ommitted from theresults shown here.Also where there have been more than one value returned viathe Amazon Details, these to have beenomitted for the sake of keeping things simplefor this small demo application. Simple is good,when trying to show how something works
                </Paragraph>
            </FlowDocument>
        </FlowDocumentPageViewer>
    </Grid>

    <ItemsControl ItemsSource="{Binding SearchRectangles}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                    <Rectangle Fill="#99FFFF00" Width="{Binding Width}"  Height="{Binding Height}"  Tag="{Binding Text}"  MouseDown="Rectangle_MouseDown">
                        <Rectangle.Style>
                            <Style TargetType="{x:Type Rectangle}">
                                <Style.Triggers>
                                    <Trigger Property="IsMouseOver" Value="True">
                                        <Setter Property="BitmapEffect">
                                            <Setter.Value>
                                                <OuterGlowBitmapEffect GlowColor="BurlyWood" GlowSize="7"/>
                                            </Setter.Value>
                                        </Setter>
                                    </Trigger>
                                </Style.Triggers>
                            </Style>
                        </Rectangle.Style>

                    </Rectangle>
                </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsControl.ItemContainerStyle>
            <Style>
                <Setter Property="Canvas.Top" Value="{Binding Top}"/>
                <Setter Property="Canvas.Left" Value="{Binding Left}"/>
            </Style>
        </ItemsControl.ItemContainerStyle>
    </ItemsControl>

</Grid>
</Grid>

代码语言:javascript
运行
复制
public partial class Window1 : Window
{
    public static readonly DependencyProperty SearchTextProperty = DependencyProperty.Register("SearchText",
                                            typeof(string),
                                            typeof(Window1));

    public static readonly DependencyProperty SearchRectanglesProperty = DependencyProperty.Register("SearchRectangles",
                    typeof(ICollection<SearchRectangle>),
                    typeof(Window1));



    public IList<string> SearchTokens { get; set; }


    public Window1()
    {
        InitializeComponent();

        SearchRectangles = new ObservableCollection<SearchRectangle>();

        _searchButton.Click += delegate
        {
            DoSearch();
        };

        _listItems.Click += delegate
        {
            SearchTokens = new List<string>();
            SearchTokens.Add("been");
            SearchTokens.Add("Amazon");
            SearchTokens.Add("following");              
            DoSearch(SearchTokens);

        };

        _searchTextBox.KeyDown += delegate(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                DoSearch();
            }
        };
    }


    public void DoSearch(IList<string> searchTokens)
    {

        SearchRectangles.Clear();

        if (searchTokens == null)
            return;

        foreach (string token in searchTokens)
        {
            SearchText = token;
            DoSearch();
        }
    }

    public string SearchText
    {
        get { return GetValue(SearchTextProperty) as string; }
        set { SetValue(SearchTextProperty, value); }
    }

    public ICollection<SearchRectangle> SearchRectangles
    {
        get { return GetValue(SearchRectanglesProperty) as ICollection<SearchRectangle>; }
        set { SetValue(SearchRectanglesProperty, value); }
    }

    private void DoSearch()
    {
        DoSearch(false);
    }

    private void DoSearch(bool clearExisting)
    {
        if( clearExisting == true ) 
            SearchRectangles.Clear();
        if (SearchText.Length == 0)
        {
            return;
        }

        DoSearch(this);
    }

    private void DoSearch(DependencyObject searchIn)
    {
        if (searchIn == null)
        {
            return;
        }

        var contentHost = searchIn as IContentHost;

        if (contentHost != null)
        {
            DoSearch(contentHost as UIElement, contentHost);
        }
        else
        {
            var documentViewerBase = searchIn as DocumentViewerBase;

            if (documentViewerBase != null)
            {
                //extract the content hosts from the document viewer
                foreach (var pageView in documentViewerBase.PageViews)
                {
                    contentHost = pageView.DocumentPage as IContentHost;

                    if (contentHost != null)
                    {
                        DoSearch(documentViewerBase, contentHost);
                    }
                }
            }
        }

        //recurse through children
        var childCount = VisualTreeHelper.GetChildrenCount(searchIn);

        for (var i = 0; i < childCount; ++i)
        {
            DoSearch(VisualTreeHelper.GetChild(searchIn, i));
        }
    }

    private void DoSearch(UIElement uiHost, IContentHost contentHost)
    {
        if (uiHost == null)
        {
            return;
        }

        var textBlock = contentHost as TextBlock;

        if (textBlock != null)
        {
            //this has the side affect of converting any plain string content in the TextBlock into a hosted Run element
            //that's bad in that it is unexpected, but good in that it allows us to access the hosted elements in a
            //consistent fashion below, rather than special-casing TextBlocks with text only content
            var contentStart = textBlock.ContentStart;
        }

        var hostedElements = contentHost.HostedElements;

        while (hostedElements.MoveNext())
        {
            var run = hostedElements.Current as Run;

            if (run != null && !string.IsNullOrEmpty(run.Text))
            {
                ApplyHighlighting(run.Text, delegate(int start, int length)
                {
                    var textPointer = run.ContentStart;
                    textPointer = textPointer.GetPositionAtOffset(start, LogicalDirection.Forward);
                    var leftRectangle = textPointer.GetCharacterRect(LogicalDirection.Forward);
                    textPointer = textPointer.GetPositionAtOffset(length, LogicalDirection.Forward);
                    var rightRectangle = textPointer.GetCharacterRect(LogicalDirection.Backward);
                    var rect = new Rect(leftRectangle.TopLeft, rightRectangle.BottomRight);
                    var translatedPoint = uiHost.TranslatePoint(new Point(0, 0), null);
                    rect.Offset(translatedPoint.X, translatedPoint.Y);
                    return rect;
                });

            }
        }
    }

    private void ApplyHighlighting(string text, Func<int, int, Rect> getRectHandler)
    {
        var currentIndex = 0;

        while (true)
        {
            var index = text.IndexOf(SearchText, currentIndex, StringComparison.CurrentCultureIgnoreCase);

            if (index == -1)
            {
                return;
            }

            var rect = getRectHandler(index, SearchText.Length);

            if (rect != Rect.Empty)
            {
                SearchRectangles.Add(new SearchRectangle(rect.Top, rect.Left, rect.Width, rect.Height,SearchText));
            }

            currentIndex = index + SearchText.Length;
        }
    }

    private void Rectangle_MouseDown(object sender, MouseEventArgs e)
    {
        Rectangle r = sender as Rectangle;
        MessageBox.Show(r.Tag.ToString());
    }

    private void FlowDocumentPageViewer_PageViewsChanged(object sender, EventArgs e)
    {

    }

    private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        DoSearch(SearchTokens);
    }

}

public class SearchRectangle
{
    private readonly double _top;
    private readonly double _left;
    private readonly double _width;
    private readonly double _height;
    private readonly string _text;

    public SearchRectangle(double top, double left, double width, double height,string text)
    {
        _top = top;
        _left = left;
        _width = width;
        _height = height;
        _text = text;

    }

    public string Text
    {
        get { return _text; }
    }

    public double Top
    {
        get { return _top; }
    }

    public double Left
    {
        get { return _left; }
    }

    public double Width
    {
        get { return _width; }
    }

    public double Height
    {
        get { return _height; }
    }
}

最好的

巴拉。

EN

回答 2

Stack Overflow用户

发布于 2009-11-19 08:25:09

看起来很容易的解决方案是在搜索时实际编辑文档以执行排序,在清除搜索结果或为其他目的需要未经编辑的文档(例如保存文档)时,请记住将其编辑回原来的位置。

可以使用code I posted in this answer搜索文档中的文本。在您的示例中,您不需要将选择设置为找到的每个范围,而是希望将范围设置为如下所示:

代码语言:javascript
运行
复制
public void HilightMatches(TextRange searchRange, string searchText)
{
  var start = searchRange.Start;
  while(start != searchRange.End)
  {
    var foundRange = FindTextInRange(
      new TextRange(start, searchRange.End),
      searchText);

    if(foundRange==null) return;
    // Here is the meat...
    foundRange.ApplyPropertyValue(TextElement.BackgroundProperty, Brushes.Yellow);
    start = foundRange.End;
  }
}

要完成这幅画,你需要一种方法来清除当你做完。若干备选方案:

  1. 保存已设置的范围,以便您只需使用ApplyPropertyValue应用Brushes.Transparent背景(简单,但这将删除以前设置的任何背景)
  2. 将找到的每个范围拆分为运行,并保存每个运行列表,每个运行列表都有其原始的背景色,因此在处理文档之前很容易恢复
  3. 保存整个文档,如果文档位于RichTextBox中,用户将不被允许编辑文档,那么就可以简单地恢复
  4. 保存整个文档,并恢复它以删除文件中的
  5. 。确保您的TextBoxBase.UndoLimit随着您的hilighting而增加,然后要删除hilighting,只需按hilight调用TextBoxBase.Undo()一次。
票数 0
EN

Stack Overflow用户

发布于 2009-11-20 00:28:02

尝试这个解决方案http://rredcat.blogspot.com/2009/11/zoom-and-page-chahged-events-for.html

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1756144

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档