Столкнулся с необходимостью выделения фрагмента текста в TextBlock, а именно определённых ключевых слов по которым были отфильтрованы элементы ListBox , этот текстовый блок собственно и содержащие
XAML, мой ваиант
<ListBox Name="ProcedureList" ItemsSource="{Binding Path=ProceduresView.View}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Name="ProcedurePanel" PreviewMouseDown="ProcedurePanel_OnPreviewMouseDown">
<DockPanel Width="{c:Binding ElementName=MainPanel, Path=Width-40}">
<!--<TextBlock Name="MainText" TextWrapping="Wrap" FontSize="16" Text="{Binding Path=title}" HorizontalAlignment="Left" />-->
<htb:HighlightTextBlock Name="MainText" TextWrapping="Wrap" FontSize="16" Text="{Binding Path=title}" HorizontalAlignment="Left">
<htb:HighlightTextBlock.HighlightRules>
<htb:HighlightRule
IgnoreCase="{Binding IgnoreCase, Source={StaticResource SourceVm}}"
HightlightedText="{Binding Path=title, Converter={StaticResource getFilter}}">
<htb:HighlightRule.Highlights>
<htb:HighlightBackgroung Brush="Yellow"/>
</htb:HighlightRule.Highlights>
</htb:HighlightRule>
</htb:HighlightTextBlock.HighlightRules>
</htb:HighlightTextBlock>
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
XAML, изменённый согласно рекомендациям VladD
<ListBox Name="ProcedureList" ItemsSource="{Binding Path=ProceduresView.View}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Name="ProcedurePanel" PreviewMouseDown="ProcedurePanel_OnPreviewMouseDown">
<DockPanel Width="{c:Binding ElementName=MainPanel, Path=Width-40}">
<!--<TextBlock Name="MainText" TextWrapping="Wrap" FontSize="16" Text="{Binding Path=title}" HorizontalAlignment="Left" />-->
<htb:HighlightTextBlock Name="MainText" TextWrapping="Wrap" FontSize="16"
Text="{Binding Path=title}" HorizontalAlignment="Left">
<htb:HighlightTextBlock.Resources>
<htb:HighlightRule x:Key="HR"
IgnoreCase="{Binding IgnoreCase, Source={StaticResource SourceVm}}"
HightlightedText="{Binding Path=DataContext.title, Source={x:Reference MainText}, Converter={StaticResource getFilter}}">
<htb:HighlightRule.Highlights>
<htb:HighlightBackgroung Brush="Yellow"/>
</htb:HighlightRule.Highlights>
</htb:HighlightRule>
</htb:HighlightTextBlock.Resources>
<htb:HighlightTextBlock.HighlightRules>
<htb:HighlightRulesCollection>
<StaticResource ResourceKey="HR"/>
</htb:HighlightRulesCollection>
</htb:HighlightTextBlock.HighlightRules>
</htb:HighlightTextBlock>
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Используется компонент написанный нашим соотечественником с открытым исходным Компонент
Описание компонента
Закомментированный код это старый TexBlock без выделения
Новый компонент HighlightTextBlock прекрасно выделяет текст если использовать статический ресурс, как в примере, но когда я пытаюсь его привязать к текущему тексту он не может найти это поле :( , я новенький в WPF помогите разобраться с
HightlightedText="{Binding Path=title, Converter={StaticResource getFilter}}"
как верно привязать это свойство к title ?
Мне дали совет по реструктуризации XAML, через ресурсы , это частично решило проблему (я успешно получил текст title в конвертере), но элемент перестал выполнять свои функции (выделение)
структура DataContext
public ObservableCollection<Procedure> Procedures { set; get; }
public CollectionViewSource ProceduresView { set; get; } = new CollectionViewSource();
....
Procedures = new ObservableCollection<Procedure>();
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<Setting.Filter> arr = new ObservableCollection<Setting.Filter>();
arr.Add(sfilter);
if (Utils.AssignedProcedureFromFilter(procedure, arr)) flag = true;
}
else flag = true;
e.Accepted = flag;
}
Видео с описанием проблемы
Упрощённый проект эмитирующий мой функционал
Если вы пользуетесь MVVM, то ваш title должен быть открытым свойством в вашей VM. То есть, в DataContext'е.
Если вы привязываетесь не к DataContext'у, то вы должны указать Source (если вы привязываетесь к какому-то другому объекту) или ElementName (если к свойству другого контрола).
Обновление: Ваш случай, на самом деле, более серьёзный. DataContext у вас, судя по всему, правильный. Но ваше Binding-выражение находится внутри сеттера свойства HighlightRules, которое не является частью визуального дерева (т. к. не доступно как Child-элемент вашего контрола). А элементы, которые не находятся внутри визуального дерева, принимают участие в привязках лишь ограничено: в них нет ни наследования DataContext'а, ни доступа по имени через ElementName. В качестве решения должна сработать привязка к элементу через x:Reference. В моём (сильно порезанном) тестовом примере срабатывает HightlightedText="{Binding Path=DataContext.title, Source={x:Reference MainText}}".
Но, если прямо заменить на это, срабатывает странная ошибка:
'Не удается вызвать MarkupExtension.ProvideValue из-за циклической зависимости. Свойства внутри MarkupExtension не могут ссылаться на объекты, ссылающиеся на результат MarkupExtension.
Метод обхода ошибки нашёлся здесь: нужно положить ваш элемент в ресурсы. Получаем вот такое:
<htb:HighlightTextBlock Name="MainText" TextWrapping="Wrap" FontSize="16"
Text="{Binding Path=title}" HorizontalAlignment="Left">
<htb:HighlightTextBlock.Resources>
<htb:HighlightRule x:Key="HR"
IgnoreCase="{Binding IgnoreCase, Source={StaticResource SourceVm}}"
HightlightedText="{Binding Path=DataContext.title, Source={x:Reference MainText},
Converter={StaticResource getFilter}}">
<htb:HighlightRule.Highlights>
<htb:HighlightBackgroung Brush="Yellow"/>
</htb:HighlightRule.Highlights>
</htb:HighlightRule>
</htb:HighlightTextBlock.Resources>
<htb:HighlightTextBlock.HighlightRules>
<local:HighlightRulesCollection>
<StaticResource ResourceKey="HR"/>
</local:HighlightRulesCollection>
</htb:HighlightTextBlock.HighlightRules>
</htb:HighlightTextBlock>
Сборка персонального компьютера от Artline: умный выбор для современных пользователей