TextBlock с подсветкой текста

213
10 ноября 2017, 06:58

Столкнулся с необходимостью выделения фрагмента текста в 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;
}

Видео с описанием проблемы

Упрощённый проект эмитирующий мой функционал

Answer 1

Если вы пользуетесь 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>
READ ALSO
CancellationToken: почему структура?

CancellationToken: почему структура?

Почему CancellationToken реализован как структура? Ведь структура является типом значения, как тогда реализован данный механизм?

247
WPF/MVVM объединить модели во ViewModel

WPF/MVVM объединить модели во ViewModel

Буду излагать суть проблемы максимально краткоИмеется 2 модели:

223
C#, MySql Connection must be valid and open

C#, MySql Connection must be valid and open

Вот дебильный быть может вопрос

199
C# MySql как конвертировать mysql таблицу в excel

C# MySql как конвертировать mysql таблицу в excel

Добрый вечер господа как конвертировать mysql таблицу в excel на C#Я установил эти ссылки(подключил пакеты):

251