tags:

views:

169

answers:

5

I have one TextBox and one listbox for searching a collection of data. While searching a text inside a Listbox if that matching string is found anywhere in the list it should show in Green color with Bold.

eg. I have string collection like "Dependency Property, Custom Property, Normal Property". If I type in the Search Text box "prop" all the Three with "prop" (only the word Prop) should be in Bold and its color should be in green. Any idea how it can be done?.

Data inside listbox is represented using DataTemplate.

+3  A: 

I've created a HighlightTextBehavior that you can attach to a TextBlock within your list item templates (you'll need to add a reference to System.Windows.Interactivity to your project). You bind the behavior to a property containing the text you want to highlight, and it does the rest.

At the moment, it only highlights the first instance of the string. It also assumes that there is no other formatting applied to the text.

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

Here's an example of how you use it:

    <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>
Samuel Jack
Interesting. Thnx for the light .
Kishore Kumar
A: 

Hi jack ,

  I have the same requirement for highlighting the matching substrings in SilverlightListbox.I am working in Silverlight4.0.I have replicated your code.But i am getting the error near New UIPropertyMetadata.and also i am binding the listbox with collection of data using itemssource in .xaml.cs file.Can you please send me the code to [email protected] am in need of Help.your help will be appreciated.

Thanks Sri

sri
A: 

Hi,

I am New to Silverlight Programming,Now working in Silverlight4.0 version.Now i have requirement that i will be having one textbox and one listbox.I binding the Lsitbox with collections thru programatically with Itemsource.When user types in the textbox,the if that typed text is present in the listbox i need to highlight that text in the listbox with red color.Can any one help in this regard.Your help will be appreacited.Thanks Sri

sri
A: 

hi,

i tried the above code but its not working to me. if u can please provide a sample project it would be great help.

thank you harsha

harsha
A: 

hi jack,

i tried ur code in silverlight 4. the entered text is not highlighting no errors but donnot know why the highlighting part is not working

harsha