Это сложно.
Пока это только часть решения, но вот пример, чтобы выделить поиск во всех текстовых блоках в VisualTree объекта root.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
public class GlobalTextHighlighter
{
public static Brush GetHighlightBackground(DependencyObject obj)
{
return (Brush)obj.GetValue(HighlightBackgroundProperty);
}
public static void SetHighlightBackground(DependencyObject obj, Brush value)
{
obj.SetValue(HighlightBackgroundProperty, value);
}
// Using a DependencyProperty as the backing store for HighlightBackground. This enables animation, styling, binding, etc...
public static readonly DependencyProperty HighlightBackgroundProperty =
DependencyProperty.RegisterAttached("HighlightBackground", typeof(Brush), typeof(GlobalTextHighlighter), new PropertyMetadata(Brushes.Yellow, new PropertyChangedCallback(RefreshHighlighting)));
public static Brush GetHighlightForeground(DependencyObject obj)
{
return (Brush)obj.GetValue(HighlightForegroundProperty);
}
public static void SetHighlightForeground(DependencyObject obj, Brush value)
{
obj.SetValue(HighlightForegroundProperty, value);
}
// Using a DependencyProperty as the backing store for HighlightForeground. This enables animation, styling, binding, etc...
public static readonly DependencyProperty HighlightForegroundProperty =
DependencyProperty.RegisterAttached("HighlightForeground", typeof(Brush), typeof(GlobalTextHighlighter), new PropertyMetadata(Brushes.Black, new PropertyChangedCallback(RefreshHighlighting)));
public static string GetSearchText(DependencyObject obj)
{
return (string)obj.GetValue(SearchTextProperty);
}
public static void SetSearchText(DependencyObject obj, string value)
{
obj.SetValue(SearchTextProperty, value);
}
// Using a DependencyProperty as the backing store for SearchText. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SearchTextProperty =
DependencyProperty.RegisterAttached("SearchText", typeof(string), typeof(GlobalTextHighlighter), new PropertyMetadata(string.Empty, new PropertyChangedCallback(RefreshHighlighting)));
private static void RefreshHighlighting(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if(d != null)
{
try
{
Brush background = (Brush)d.GetValue(HighlightBackgroundProperty);
Brush foreground = (Brush)d.GetValue(HighlightForegroundProperty);
string highlightText = (string)d.GetValue(SearchTextProperty);
FindVisualChildren<TextBlock>(d)
.ToList()
.ForEach(textBlock =>
{
try
{
string text = textBlock.Text;
if (!string.IsNullOrEmpty(text))
{
if (string.IsNullOrEmpty(highlightText))
{
textBlock.Text = text;
}
else
{
int index = text.IndexOf(highlightText, StringComparison.CurrentCultureIgnoreCase);
if (index < 0)
textBlock.Text = text;
else
textBlock.Inlines.Clear();
while (index >= 0)
{
textBlock.Inlines.AddRange(new Inline[]
{
new Run(text.Substring(0, index)),
new Run(text.Substring(index, highlightText.Length))
{
Background = background,
Foreground = foreground
}
});
text = text.Substring(index + highlightText.Length);
index = text.IndexOf(highlightText, StringComparison.CurrentCultureIgnoreCase);
if (index < 0)
{
textBlock.Inlines.Add(new Run(text));
}
}
}
}
}
catch
{ }
});
}
catch { }
}
}
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
}
И вы можете использовать его на root объекте, из которого хотите выполнить поиск.
Пример:
<TextBox x:Name="GlobalSearchTextBox"
Text="{Binding GlobalSearch, UpdateSourceTrigger=PropertyChanged, Delay=100}"/>
<DockPanel local:GlobalTextHighlighter.SearchText="{Binding GlobalSearch}"
local:GlobalTextHighlighter.HighlightBackground="Orange"
local:GlobalTextHighlighter.HighlightForeground="Blue">
<!-- ... -->
</DockPanel>
Он основан на WPF TextBlock Highlighter и Найдите все элементы управления в окне WPF по типу .
Как я уже сказал, это еще не полное решение.
И оно имеет некоторые недостатки.
- Он не работает со всеми компонентами, использующими AccessText, например Labels.
- Он не работает с редактируемыми компонентами, такими как TextBoxs или RichTextBox.
- Это не так просмотр от одного совпадения к другому.
- Если вы хотите управлять вложенными ScrollAreas.
Надеюсь, это уже поможет приблизиться к решению.