2010-05-24 6 views
5

Ho un TextBox e una listbox per la ricerca di una raccolta di dati. Durante la ricerca di un testo all'interno di una casella di riepilogo, se la stringa corrispondente viene trovata in qualsiasi punto dell'elenco, deve essere visualizzata in verde con grassetto.Come evidenziare le sotto-stringhe corrispondenti all'interno di un ListBox?

es. Ho una collezione di stringhe come "Proprietà dipendenza, Proprietà personalizzata, Proprietà normale". Se digito la casella "Prop" del testo di ricerca tutti i tre con "prop" (solo la parola Prop) dovrebbero essere in grassetto e il suo colore dovrebbe essere in verde. Qualche idea su come può essere fatto?

I dati all'interno della casella di riepilogo sono rappresentati utilizzando DataTemplate.

risposta

8

Ho creato un comando HighlightText che è possibile allegare a un TextBlock all'interno dei modelli di elementi dell'elenco (è necessario aggiungere un riferimento a System.Windows.Interactivity al progetto). Leghi il comportamento a una proprietà contenente il testo che vuoi evidenziare, e fa il resto.

Al momento evidenzia solo la prima istanza della stringa. Suppone anche che non ci sia altra formattazione applicata al testo.

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

Ecco un esempio di come lo si utilizza:

<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

Interessante. Thnx per la luce. –