2010-05-24 3 views
5

Ich habe eine TextBox und eine Listbox zum Durchsuchen einer Sammlung von Daten. Wenn Sie einen Text in einer Listbox suchen, wenn dieser übereinstimmende String irgendwo in der Liste gefunden wird, sollte er in grüner Farbe mit Fett angezeigt werden.Wie markieren übereinstimmende Sub-Strings innerhalb einer ListBox?

z. Ich habe String-Sammlung wie "Abhängigkeitseigenschaft, benutzerdefinierte Eigenschaft, normale Eigenschaft". Wenn ich das Suchfeld "prop" eintippe, sollten alle Three mit "prop" (nur das Wort Prop) fett gedruckt werden und die Farbe sollte grün sein. Irgendeine Idee, wie es gemacht werden kann ?.

Daten innerhalb der Listbox werden mit DataTemplate dargestellt.

Antwort

8

Ich habe ein HighlightTextBehavior erstellt, das Sie an einen TextBlock in Ihren Listenelementvorlagen anhängen können (Sie müssen Ihrem Projekt einen Verweis auf System.Windows.Interactivity hinzufügen). Sie binden das Verhalten an eine Eigenschaft, die den zu markierenden Text enthält, und erledigt den Rest.

Im Moment wird nur die erste Instanz der Zeichenfolge hervorgehoben. Außerdem wird davon ausgegangen, dass keine andere Formatierung auf den Text angewendet wird.

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

Hier ist ein Beispiel dafür, wie Sie es verwenden:

<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

Interessant. Thnx für das Licht. –

Verwandte Themen