private async void search_Click(object sender, RoutedEventArgs e) { search.IsEnabled = false; Cursor = Cursors.Wait; string word = searchText.Text; bool isCaseSensitive = caseSensitive.IsChecked == true; IEnumerable <WordLocation> wordLocs = (useWildcards.IsChecked == true) ? await _wordSearcher.WildcardSearchAsync(word, isCaseSensitive) : await _wordSearcher.SearchAsync(word, isCaseSensitive); List <WordLocation> locations = wordLocs.ToList(); status.Text = $"{locations.Count} found"; searchResults.ItemsSource = locations; List <Tuple <WordLocation, TextRange> > ranges = new List <Tuple <WordLocation, TextRange> >(); TextPointer pointer = paragraph.ContentStart; while (pointer != null) { if (pointer.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text) { foreach (WordLocation loc in locations) { TextPointer start = pointer.GetPositionAtOffset(loc.Location), end = start.GetPositionAtOffset(loc.Word.Length); ranges.Add(Tuple.Create(loc, new TextRange(start, end))); } break; } pointer = pointer.GetNextContextPosition(LogicalDirection.Forward); } // Hilite all finds yellow: Action hilite = () => { if (_ranges != null) { _ranges.ForEach(tr => tr.Item2.ClearAllProperties()); } _ranges = ranges; if (locations.Count > 0) { searchResults.SelectedIndex = 0; } _ranges.ForEach((tr) => { tr.Item2.ApplyPropertyValue(TextElement.BackgroundProperty, Brushes.Yellow); tr.Item2.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Navy); }); search.IsEnabled = true; Cursor = Cursors.Arrow; }; Dispatcher.BeginInvoke(hilite, DispatcherPriority.Background); }