2010-05-24 12 views
5

Tengo un cuadro de texto y un cuadro de lista para buscar una colección de datos. Mientras busca un texto dentro de un Listbox si esa cadena coincidente se encuentra en algún lugar de la lista, debe mostrarse en color verde con Bold.¿Cómo resaltar sub-cadenas coincidentes dentro de un ListBox?

por ejemplo. Tengo una colección de cadenas como "Propiedad de dependencia, propiedad personalizada, propiedad normal". Si escribo en el cuadro de texto de búsqueda "prop", todos los tres con "prop" (solo la palabra Prop) deben estar en negrita y su color debe estar en verde. ¿Alguna idea de cómo se puede hacer?

Los datos dentro del listbox se representan utilizando DataTemplate.

Respuesta

8

He creado un HighlightTextBehavior que puede adjuntar a un TextBlock dentro de las plantillas de elementos de la lista (deberá agregar una referencia a System.Windows.Interactivity para su proyecto). Vincula el comportamiento a una propiedad que contiene el texto que desea resaltar, y hace el resto.

Por el momento, solo resalta la primera instancia de la cadena. También asume que no hay otro formato aplicado al texto.

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

Aquí hay un ejemplo de cómo lo usa:

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

interesante. Thnx por la luz. –

Cuestiones relacionadas