TextBlock,文字突出显示

时间:2017-11-09 19:55:05

标签: c# wpf xaml

面对需要在TextBlock中选择文本片段,即已过滤ListBox的某些关键字,此文本块本身并包含 XAML变体,title属性未绑定

<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>

使用我们的同胞用开源编写的组件

Component

Description of component

评论代码是一个没有选择的旧TexBlock

如果您使用静态资源,新的HighlightTextBlock组件会完美地选择文本,如示例所示,但是当我尝试将其绑定到当前文本时,它找不到此字段:(,我是新的WPF帮助弄明白

HightlightedText="{Binding Path=title, Converter={StaticResource getFilter}}"

如何正确地将此属性锚定到标题?

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; }
    ....
}
....

// Simple filtering        
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;
}

Video with problem description

Simplified project emitting my functional

在讲俄语的论坛上,他们向我解释说:

  

事实上,你的情况更为严重。 DataContext你,显然,   正确对象,真爱。但是你的Binding表达式在HighlightRules中   属性设置器,它不是可视树的一部分(因为它是   不可用作您控件的子元素)。和元素   不在视觉树内,只参与绑定   有限:它们不继承DataContext,也不通过名称访问   的ElementName。作为解决方案,通过x:Reference绑定到元素。在我的   (严重削减)测试用例,HightlightedText =&#34; {Binding Path =   触发DataContext.title,Source = {x:Reference MainText}}。&#34;   但是,如果直接替换为此,则会出现一个奇怪的错误:&#39;不能   调用MarkupExtension。由于循环依赖性,ProvideValue。该   MarkupExtension中的属性不能引用那些对象   引用MarkupExtension结果。

此处找到了错误的解决方法:您需要将元素放在资源中。我们得到这个: 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.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>

我获得了关于XAML重组的建议,通过资源,这部分解决了问题(我成功地在转换器中获得了标题文本),但元素停止执行其功能(分配)在讨论期间,它是建议组件本身应该最终确定

  

@iRumba:从理论上说,如果你提出的话,整个伎俩都不是必要的   HighlighRule集合(也)在可视化树中。那么   DataContext将自动继承,并在想法上绑定   通过ElementName也可以。

     

@iRumba:我不记得了。看来,有必要   指定将所有HighlightRule添加为LogicalChildren(为此目的   在想法上,有必要重新定义受保护的内部覆盖   IEnumerator LogicalChildren)。这是一个复杂的,先进的   技术,是的。

对不起谷歌翻译

1 个答案:

答案 0 :(得分:0)

找到解决方案

 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));
}

使用

<parser:SearchHightlightTextBlock SearchText="{Binding Path=title, Converter={StaticResource getFilter}}" Text="{Binding title}"/>