2010-05-24 85 views
5

我有一個文本框和一個用於搜索數據集合的列表框。在列表框中搜索文本時,如果在列表中的任何位置找到匹配的字符串,它應以綠色和粗體顯示。如何突出顯示ListBox中的匹配子字符串?

例如。我有字符串集合,如 「依賴屬性,自定義屬性,標準屬性」。如果我在搜索文本框中輸入「prop」,那麼所有帶有「prop」的三位(只有Prop字)應該用粗體顯示,其顏色應該是綠色。任何想法如何可以做到?

列表框中的數據用DataTemplate表示。

回答

8

我已經創建了一個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> 
+0

有趣。 thnx爲光明。 – 2010-05-24 10:07:14

相關問題