Zhou's profileSheva's TechSpacePhotosBlogLists Tools Help

Blog


    11/25/2007

    How To Search Text In WPF FlowDocument?

    This blog article is a reply to the recent WPF MSDN forum thread on how to efficiently search text in FlowDocument. The thread starter needs to have the same performance as the search feature in Visual Studio text editor. I don't know how Visual Studio IDE implements the search feature, but in terms of search in FlowDocument, because FlowDocument enables much richer content model, It's presumably much harder to achieve the same search performance as Visual Studio text editor.

    I have to say that the code I posted in that thread apparently has a serious performance flaw, it introduces a lot of unnecessary iterations. After digging into this issue at the weekend, I finally come up with a method which can achieve the perceived performance, and I think this should be enough at most circumstance. Based on this method, I mocked up a sample code which shows how to perform find and replace feature in FlowDocument, because find and replace is a common feature every text editing tool should provide, this might help others who need this similar feature. The following shows the core code which perform the search:

    /// <summary>
    ///
    Find the corresponding<see cref="TextRange"/> instance
    /// representing the input string given a specified text pointer position.
    /// </summary>
    ///
    <param name="position">the current text position</param>
    ///
    <param name="textToFind">input text</param>
    ///
    <param name="findOptions">the search option</param>
    ///
    <returns>An<see cref="TextRange"/> instance represeneting the matching string withing the text container.</returns>
    public TextRange GetTextRangeFromPosition(ref TextPointer position, String input, FindOptions findOptions)
    {
        Boolean matchCase = (findOptions & FindOptions.MatchCase) == FindOptions.MatchCase;
        Boolean matchWholeWord = (findOptions & FindOptions.MatchWholeWord) == FindOptions.MatchWholeWord;

        TextRange textRange = null;

        while (position != null)
        {
            if (position.CompareTo(inputDocument.ContentEnd) == 0)
            {
                break;
            }

            if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
            {
                String textRun = position.GetTextInRun(LogicalDirection.Forward);
                StringComparison stringComparison = matchCase ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase;
                Int32 indexInRun = textRun.IndexOf(input, stringComparison);

                if (indexInRun >= 0)
                {
                    position = position.GetPositionAtOffset(indexInRun);
                    TextPointer nextPointer = position.GetPositionAtOffset(input.Length);
                    textRange = new TextRange(position, nextPointer);

                    if (matchWholeWord)
                    {
                        if (IsWholeWord(textRange)) // Test if the "textRange" represents a word.
                        {
                            // If a WholeWord match is found, directly terminate the loop.
                            break;
                        }
                        else
                        {
                            // If a WholeWord match is not found, go to next recursion to find it.
                            position = position.GetPositionAtOffset(input.Length);
                            return GetTextRangeFromPosition(ref position, input, findOptions);
                        }
                    }
                    else
                    {
                        // If a none-WholeWord match is found, directly terminate the loop.
                        position = position.GetPositionAtOffset(input.Length);
                        break;
                    }
                }
                else
                {
                    // If a match is not found, go over to the next context position after the "textRun".
                    position = position.GetPositionAtOffset(textRun.Length);
                }
            }
            else
            {
                //If the current position doesn't represent a text context position, go to the next context position.
                // This can effectively ignore the formatting or embedded element symbols.
                position = position.GetNextContextPosition(LogicalDirection.Forward);
            }
        }

        return textRange;
    }

    The code above is part of my FindAndReplaceManager helper class implementation, you can refer to the attachment for the complete source code. The code should be pretty straightforward as I've commentted it. The FindAndReplaceManager can support search options such as FindOptions.MatchCase and FindOptions.MatchWholeWord, aka two commonly used search options. For simplicity, I don't implement reverse search, since this should be really straightforward, instead of using LogicalDirection.Forward, you could use LogicalDirection.Backward.

    As I've said, the FindAndReplaceManager should be able to achieve perceived performance at most situation, if you need hard best performance. You'd better choose a more sophisticated search algorithm instead of the bare-bones "start-to-end" search algorithm as is illustrated in the code above.

    Another alternative you could choose is the internal undocumented search API provided by WPF. The System.Windows.Documents.TextFindEngine class has a static "Find" method, this method is widely used in build-in document readers and viewers such as FlowDocumentReader, FlowDocumentPageViewer, and FlowDocumentScrollViewer. Because TextFindEngine has a much better understanding of the underlying document content structure, it should provide the hard performance benefit you expect. The following helper method shows how to use this method:

    using System;
    using System.Windows;
    using System.Reflection;
    using System.Globalization;
    using System.Windows.Documents;

    namespace Sheva.Windows.Documents
    {
        [Flags]
        public enum FindFlags
        {
            FindInReverse = 2,
            FindWholeWordsOnly = 4,
            MatchAlefHamza = 0x20,
            MatchCase = 1,
            MatchDiacritics = 8,
            MatchKashida = 0x10,
            None = 0
        }

        public static class DocumentHelper
        {
            private static MethodInfo findMethod = null;

            public static TextRange FindText(TextPointer findContainerStartPosition,TextPointer findContainerEndPosition, String input, FindFlags flags, CultureInfo cultureInfo)
            {
                TextRange textRange = null;
                if (findContainerStartPosition.CompareTo(findContainerEndPosition) < 0)
                {
                    try
                    {
                        if (findMethod == null)
                        {
                            findMethod = typeof(FrameworkElement).Assembly.GetType("System.Windows.Documents.TextFindEngine").
                                   GetMethod("Find", BindingFlags.Static | BindingFlags.Public);
                        }
                        Object result = findMethod.Invoke(null, new Object[] { findContainerStartPosition,
                        findContainerEndPosition,
                        input, flags, CultureInfo.CurrentCulture });
                        textRange = result as TextRange;
                    }
                    catch (ApplicationException)
                    {
                        textRange = null;
                    }
                }

                return textRange;
            }
        }
    }

    Because TextFindEngine.Find() is a non-public API, we should use a bit of reflection code to call it. If you are working on pesonal project, feel free to use it as an alternative, but never ever use this method in production code.

    WPF should provide a much better built-in public API to perform search operation in FlowDocument. I don't know what type of future plan WPF team has, but from my educated guess, WPF should have a much better support on this in the near future.

    Attachment: SearchInFlowDocumentDemo.zip

    Comments (28)

    Please wait...
    Sorry, the comment you entered is too long. Please shorten it.
    You didn't enter anything. Please try again.
    Sorry, we can't add your comment right now. Please try again later.
    To add a comment, you need permission from your parent. Ask for permission
    Your parent has turned off comments.
    Sorry, we can't delete your comment right now. Please try again later.
    You've exceeded the maximum number of comments that can be left in one day. Please try again in 24 hours.
    Your account has had the ability to leave comments disabled because our systems indicate that you may be spamming other users. If you believe that your account has been disabled in error please contact Windows Live support.
    Complete the security check below to finish leaving your comment.
    The characters you type in the security check must match the characters in the picture or audio.
    Zhou Yong has turned off comments on this page.
    Nov. 27
    Nov. 21
    Nov. 21
    Nov. 20
    No namewrote:
    労働問題 収益物件不動産売却などにはマンション査定土地売買1戸建て売却が含まれる賃貸 住宅不動産 賃貸賃貸マンション新築マンションもしっかりカバーしてありすごく充実したさいとでもちろん投資を目的の方やリフォームをしたい人もすごく参考になるだう。ところで今,SEO対策などいまはやっているがホームページ制作会社にいらいしてもうまくはいかないようだ。最近私は、資産運用にこっていて税金対策にインテリアを集めている。もちろんファッションにこだわりブランド品や下着,ランジェリーにはこだわりがある。 化粧品ダイエット用品高価なものがよく家具も最高級しか買わない、先日海外旅行にいってきてお土産に外車結婚指輪と高級時計をかったが、日本でしらべたら通販ですごく安く売っていた。 物件探しは広島 不動産 岡山 不動産 松山市 不動産 香川県 不動産 徳島 不動産 高知 不動産 高松 不動産をフルカバーしてます大手で 和歌山 富山 滋賀 石川 山梨 新潟 沖縄 大分 鹿児島 宮崎 熊本 高知
    Nov. 20
    Nov. 19
    No namewrote:
    [url=http://www.warhammer100.com/][b]buy warhammer gold[/b][/url]
    [url=http://www.cheaperzone.com/][b]warhammer gold[/b][/url]
    [url=http://www.cheaperzone.com/News/News.Html][b]buy warhammer gold[/b][/url]
    [url=http://www.buyfastgold.com/][b]warhammer gold[/b][/url]
    [url=http://www.buyfastgold.com/news/][b]buy warhammer gold[/b][/url]
    [url=http://www.game4power.com/][b]wow gold[/b][/url]
    [url=http://www.game4power.com/news/][b]buy wow gold[/b][/url]
    [url=http://www.wowgoldone.com/][b]wow gold[/b][/url]
    [url=http://www.wowgoldone.com/][b]buy wow gold[/b][/url]
    [url=http://www.game4power.com/][b]world of warcraft gold[/b][/url]
    [url=http://www.wowgoldone.com/][b]world of warcraft gold[/b][/url]
    [url=http://www.gamelevelup.com/][b]wow power leveling[/b][/url]
    [url=http://itemstores.com/][b]wow item[/b][/url]
     
     
     
     
    <A href="http://www.warhammer100.com/" target=_blank><FONT size=4><B>warhammer gold</B></FONT></A> <FONT size=4></FONT><A href="http://www.warhammer100.com/" target
    <A href="http://www.warhammer100.com/" target=_blank><FONT size=4><B>warhammer gold</B></FONT></A> <FONT size=4></FONT><A href="http://www.warhammer100.com/" target=_blank><FONT size=4><B>buy warhammer gold</B></FONT></A><BR><A href="http://www.cheaperzone.com/" target=_blank><FONT size=4><B>warhammer gold</B></FONT></A><FONT size=4></FONT> <A href="http://www.cheaperzone.com/News/News.Html" target=_blank><FONT size=4><B>buy warhammer gold</B></FONT></A><BR><A href="http://www.buyfastgold.com/" target=_blank><FONT size=4><B>warhammer gold</B></FONT></A> <FONT size=4></FONT><A href="http://www.buyfastgold.com/news/" target=_blank><FONT size=4><B>buy warhammer gold</B></FONT></A><BR><A href="http://www.game4power.com/" target=_blank><FONT size=4><B>wow gold</B></FONT></A> <FONT size=4></FONT><A href="http://www.game4power.com/news/" target=_blank><FONT size=4><B>buy wow gold</B></FONT></A><BR><A href="http://www.wowgoldone.com/" target=_blank><FONT size=4><B>wow gold</B></FONT></A> <FONT size=4></FONT><A href="http://www.wowgoldone.com/" target=_blank><FONT size=4><B>buy wow gold</B></FONT></A><BR><A href="http://www.game4power.com/" target=_blank><FONT size=4><B>world of warcraft gold</B></FONT></A> <FONT size=4></FONT><A href="http://www.wowgoldone.com/" target=_blank><FONT size=4><B>world of warcraft gold</B></FONT></A><BR><A href="http://www.gamelevelup.com/" target=_blank><FONT size=4><B>wow power leveling</B></FONT></A><BR><A href="http://itemstores.com/" target=_blank><FONT size=4><B>wow item</B></FONT></A>
    Nov. 18
    Nov. 13
    Nov. 13
    Nov. 13
    Nov. 8
    Nov. 8
    Oct. 14
    No namewrote:
    客户管理 客户管理系统 营销管理系统 客户资源管理 销售管理软件 客户资料管理软件 客户资源管理软件 客户信息管理软件 客户资料管理 客户资源管理 客户信息管理 客户资料管理系统 客户资源管理系统 客户管理软件免费版砂磨机 砂磨机 砂磨机 卧式砂磨机 卧式砂磨机 卧式砂磨机 三辊研磨机 三辊研磨机 三辊研磨机 混合机 混合机 混合机 锥形混合机 锥形混合机 锥形混合机 行星动力混合机 行星动力混合机 行星动力混合机 无重力混合机 无重力混合机 无重力混合机 干粉砂浆设备 干粉砂浆设备 干粉砂浆设备 捏合机 捏合机 捏合机 导热油炉 导热油炉 导热油炉 反应釜 反应釜 反应釜 搪玻璃反应釜 搪玻璃反应釜 搪玻璃反应釜 乳化机 涂料设备 干混砂浆设备 无重力混合机 胶体磨 涂料成套设备 双螺旋混合机 北京婚庆 北京婚庆公司 400电话办证 呼吸机 制氧机亚都 亚都加湿器 亚都净化器 亚都装修卫士饰品批发 小饰品批发 韩国饰品 韩国饰品批发 premature ejaculation penis enlargement 破碎机 制砂机 球磨机 雷蒙磨 雷蒙磨粉机 鄂式破碎机 鄂式破碎机 免烧砖机 加气混凝土设备 反击式破碎机 选矿设备 安利产品 马来西亚留学网站优化 网站推广衬布代写论文代写论文 论文代写 代写论文 代写硕士论文 代写毕业论文磁力泵离心泵化工泵隔膜泵螺杆泵潜水泵油泵耐腐蚀泵
    Oct. 14
    No namewrote:
    spherical roller bearing搬运车 搬运车 电动搬运车 油桶搬运车 堆高车 电动堆高车 半电动堆高车 堆垛车 高空作业平台车 电动叉车 平衡重叉车 前移叉车 电瓶叉车苗木价格 苗木信息 标牌制作 深圳标牌 儿童摄影 北京儿童摄影 防静电鞋 淘宝刷信誉威海凤凰湖 威海海景房 大庆密封件打标机 淘宝刷信誉 TESOL/TEFL国际英语教师证书 英语教师进修及培训韩国饰品批发 代写论文 代写论文 代写论文 代写代发 论文代写 电源模块 模块电源X架 超薄灯箱> 易拉宝 展柜制作 代理服务器 游戏加速器 网络加速器 网通加速器 电信加速器 电信网通转换器 电信网通加速器 网通电信互转 网通电信互通 网络游戏加速器 美国VPN代理 美国独享VPN 美国独享IPpvc ceiling panel Spherical roller bearingsSEO优化安全鞋 劳保鞋 防砸鞋 电绝缘鞋 上海安全鞋 上海劳保鞋 江苏劳保鞋 服装软件 服装管理软件 进销存软件 进销存管理软件 服装管理系统 服装进销存软件 进销存系统 进销存管理系统 免费进销存软件吉林中医 东北特产打包机 dhl阳痿 阴茎短小 阴茎增大 早泄 前列腺炎 阴茎增粗 阴茎延长国际机票 上海国际机票 国际打折机票 国际特价机票CRM 客户管理软件 客户关系管理 免费客户管理软件 客户管理软件下载 客户信息管理系统 销售管理系统 销售管理 CRM系统 CRM软件 客户关系管理系统 客户关系管理软件
    Oct. 14
    Oct. 14
    No namewrote:
    HTML clipboard情趣用品,情趣用品,情趣用品,情趣用品,情趣,情趣,情趣,情趣,按摩棒,震動按摩棒,微調按摩棒,情趣按摩棒,逼真按摩棒,G點,跳蛋,跳蛋,跳蛋,性感內衣,飛機杯,充氣娃娃,情趣娃娃,角色扮演,性感睡衣,SM,潤滑液,威而柔,香水,精油,芳香精油,自慰套,自慰,性感吊帶襪,吊帶襪,情趣用品加盟AIO交友愛情館,情人歡愉用品,美女視訊,情色交友,視訊交友,辣妹視訊,美女交友,嘟嘟成人網,成人網站,A片,A片下載,免費A片,免費A片下載情人歡愉用品,情趣用品,成人網站,情人節禮物,情人節,AIO交友愛情館,情色,情色貼圖,情色文學,情色交友,色情聊天室,色情小說,七夕情人節,色情,情色電影,色情網站,辣妹視訊,視訊聊天室,情色視訊,免費視訊聊天,美女視訊,視訊美女,美女交友,美女,情色交友,成人交友,自拍,本土自拍,情人視訊網,視訊交友90739,生日禮物,情色論壇,正妹牆,免費A片下載,AV女優,成人影片,色情A片,成人論壇,情趣,情境坊歡愉用品,免費成人影片,成人電影,成人影城,愛情公寓,成人影片,保險套,舊情人,微風成人,成人,成人遊戲,成人光碟,色情遊戲,跳蛋,按摩棒,一夜情,男同志聊天室,肛交,口交,性交,援交,免費視訊交友,視訊交友,一葉情貼圖片區,性愛,視訊,視訊聊天,A片,A片下載,免費A片,嘟嘟成人網,寄情築園小遊戲,女同志聊天室,免費視訊聊天室,一夜情聊天室,聊天室愛情公寓,情色,舊情人,情色貼圖,情色文學,情色交友,色情聊天室,色情小說,一葉情貼圖片區,情色小說,色情,色情遊戲,情色視訊,情色電影,aio交友愛情館,色情a片,一夜情,辣妹視訊,視訊聊天室,免費視訊聊天,免費視訊,視訊,視訊美女,美女視訊,視訊交友,視訊聊天,免費視訊聊天室,情人視訊網,影音視訊聊天室,視訊交友90739,成人影片,成人交友,美女交友,微風成人,嘟嘟成人網,成人貼圖,成人電影,A片,豆豆聊天室,聊天室,UT聊天室,尋夢園聊天室,男同志聊天室,UT男同志聊天室,聊天室尋夢園,080聊天室,080苗栗人聊天室,6K聊天室,女同志聊天室,小高聊天室,上班族聊天室,080中部人聊天室,同志聊天室,聊天室交友,中部人聊天室,成人聊天室,一夜情聊天室,情色聊天室,寄情築園小遊戲
    Oct. 14
    No namewrote:
    Want to go to tibet tour? You can rely on us! We are expert in tour in tibet. based in Tibet 15 years experience, 600 private groups operated! So join us for your wondrous tibet travel! Are you interested in mysterious Lhasa travel to tibet? Why not take our Lhasa tibet trekking? You can appreciate the holiness of Lhasa tibet tour guide with our well-connected itinerary and leave a memorable recollection over life. These are China Lhasa tibet thangka packages with personal local tibet map, and private vehicle with driver + hotels + entrance fees and meals as listed for your party based on minimum 2 travelers. Tibet Buddhist Sects and Characteristics, For single person, please email us for new quotations. For any questions, please feel free to contact our customer team with our prompt and personalized travel services.
    Oct. 10
    Sept. 30
    Sept. 6

    Trackbacks

    The trackback URL for this entry is:
    http://shevaspace.spaces.live.com/blog/cns!FD9A0F1F8DD06954!638.trak
    Weblogs that reference this entry
    • None