Как выделить соответствующие подстроки внутри ListBox? - PullRequest
5 голосов
/ 24 мая 2010

У меня есть один TextBox и один список для поиска в коллекции данных. При поиске текста внутри списка, если соответствующая строка находится где-либо в списке, она должна отображаться зеленым цветом с жирным шрифтом.

например. У меня есть коллекция строк, как "Свойство зависимости, Пользовательское свойство, Обычное свойство". Если я наберу в текстовом поле поиска «prop» все три с «prop» (только слово «Prop») должны быть выделены жирным шрифтом, а его цвет - зеленым. Есть идеи, как это можно сделать?

Данные внутри списка представлены с использованием DataTemplate.

1 Ответ

8 голосов
/ 24 мая 2010

Я создал HighlightTextBehavior, который вы можете прикрепить к TextBlock в своих шаблонах элементов списка (вам нужно добавить ссылку на System.Windows.Interactivity в ваш проект).Вы привязываете поведение к свойству, содержащему текст, который вы хотите выделить, и оно делает все остальное.

На данный момент оно выделяет только первый экземпляр строки.Он также предполагает, что к тексту не применяется никакого другого форматирования.

using System.Linq;
using System.Text;
using System.Windows.Interactivity;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;

namespace StringHighlight
{
    public class HighlightTextBehavior : Behavior<TextBlock>
    {
        public string HighlightedText
        {
            get { return (string)GetValue(HighlightedTextProperty); }
            set { SetValue(HighlightedTextProperty, value); }
        }

        // Using a DependencyProperty as the backing store for HighlightedText.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty HighlightedTextProperty =
            DependencyProperty.Register("HighlightedText", typeof(string), typeof(HighlightTextBehavior), new UIPropertyMetadata(string.Empty, HandlePropertyChanged));

        private static void HandlePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            (sender as HighlightTextBehavior).HandlePropertyChanged();
        }

        private void HandlePropertyChanged()
        {
            if (AssociatedObject == null)
            {
                return;
            }

            var allText = GetCompleteText();

            AssociatedObject.Inlines.Clear();

            var indexOfHighlightString = allText.IndexOf(HighlightedText);

            if (indexOfHighlightString < 0)
            {
                AssociatedObject.Inlines.Add(allText);
            }
            else
            {
                AssociatedObject.Inlines.Add(allText.Substring(0, indexOfHighlightString));
                AssociatedObject.Inlines.Add(new Run() { 
                    Text = allText.Substring(indexOfHighlightString, HighlightedText.Length), 
                    Foreground = Brushes.Green,
                    FontWeight = FontWeights.Bold });
                AssociatedObject.Inlines.Add(allText.Substring(indexOfHighlightString + HighlightedText.Length));
            }
        }

        private string GetCompleteText()
        {
            var allText = AssociatedObject.Inlines.OfType<Run>().Aggregate(new StringBuilder(), (sb, run) => sb.Append(run.Text), sb => sb.ToString());
            return allText;
        }
    }
}

Вот пример того, как вы его используете:

    <Window x:Class="StringHighlight.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        xmlns:b="clr-namespace:StringHighlight"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.Resources>
            <x:Array x:Key="MyStrings" Type="{x:Type sys:String}">
                <sys:String>This is my first string</sys:String>
                <sys:String>Another string</sys:String>
                <sys:String>A third string, equally imaginative</sys:String>
            </x:Array>
        </Grid.Resources>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBox x:Name="SearchText"/>

        <ListBox Grid.Row="1" ItemsSource="{StaticResource MyStrings}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Grid.Row="1" Text="{Binding}">
                        <i:Interaction.Behaviors>
                            <b:HighlightTextBehavior HighlightedText="{Binding ElementName=SearchText, Path=Text}"/>
                        </i:Interaction.Behaviors>
                    </TextBlock>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...