Столкнулся с необходимостью выделения фрагмента текста в TextBlock, а именно определённых ключевых слов по которым были отфильтрованы элементы ListBox , этот текстовый блок собственно и содержащие
XAML, мой ваиант
Вариант XAML, рекомендованный VladD, не создаёт коллекцию HighlightRulesCollection (хотя казалось бы даже отрабатывает конвертер)
Используется компонент написанный нашим соотечественником с открытым исходным Компонент
Описание компонента
Закомментированный код это старый TexBlock без выделения
Новый компонент HighlightTextBlock прекрасно выделяет текст если использовать статический ресурс, как в примере, но когда я пытаюсь его привязать к текущему тексту он не может найти это поле :( , я новенький в WPF помогите разобраться с
HightlightedText="{Binding Path=title, Converter={StaticResource getFilter}}"
Изначально вопрос звучал как верно привязать это свойство к title ?
Мне дали совет по реструктуризации XAML, через ресурсы , но это не работает т.к. не создаётся HighlightRulesCollection и выделение не работает.
В ходе обсуждения было высказано предположение что следует несколько модифицировать сам компонент и поместить коллекцию HighlighRule (также) в визуальное дерево. Тогда будет автоматически наследоваться DataContext и по идее будет работать привязка через ElementName.
Подскажите как это можно реализовать? или может кто то внесёт правки в исходный код компонента ?
Альтернативный вариант , подскажите, как реализовать такого рода функционал другими методами ?
структура DataContext
public ObservableCollection
....
Procedures = new ObservableCollection
ProceduresView.Filter += Procedures_Filter;
ProceduresView.Source = Procedures;
....
public class Procedure : ObservableObject
{
....
public String title { get; set; }
....
}
....
// Просто фильтрация
void Procedures_Filter(object sender, FilterEventArgs e)
{
Procedure procedure = (Procedure) e.Item;
Boolean flag = false;
if (!string.IsNullOrEmpty(filter))
{
Setting.Filter sfilter = new Setting.Filter();
sfilter.type = "искать везде";
sfilter.text = filter;
ObservableCollection
Видео с описанием проблемы
Упрощённый проект эмитирующий мой функционал
Ответ
Нашёл работающее решение своей задачи
public class SearchHightlightTextBlock : TextBlock
{
public SearchHightlightTextBlock() : base() { }
public String SearchText
{
get { return (String)GetValue(SearchTextProperty); }
set { SetValue(SearchTextProperty, value); }
}
private static void OnDataChanged(DependencyObject source,
DependencyPropertyChangedEventArgs e)
{
TextBlock tb = (TextBlock)source;
if (tb.Text.Length == 0)
return;
string textUpper = tb.Text.ToUpper();
String toFind = ((String)e.NewValue).ToUpper();
int firstIndex = textUpper.IndexOf(toFind);
String firstStr = "";
String foundStr = "";
if (firstIndex != -1)
{
firstStr = tb.Text.Substring(0, firstIndex);
foundStr = tb.Text.Substring(firstIndex, toFind.Length);
}
String endStr = tb.Text.Substring(firstIndex + toFind.Length,
tb.Text.Length - (firstIndex + toFind.Length));
tb.Inlines.Clear();
tb.FontSize = 16;
var run = new Run();
run.Text = firstStr;
tb.Inlines.Add(run);
run = new Run();
run.Background = Brushes.Yellow;
run.Text = foundStr;
tb.Inlines.Add(run);
run = new Run();
run.Text = endStr;
tb.Inlines.Add(run);
}
public static readonly DependencyProperty SearchTextProperty =
DependencyProperty.Register("SearchText",
typeof(String),
typeof(SearchHightlightTextBlock),
new FrameworkPropertyMetadata(null, OnDataChanged));
}
Использовать вот так
Не совсем элегантное решение , но работает привязка и все дела :)
Комментариев нет:
Отправить комментарий