windows8开发笔记(6)-ListView筛选汉字以及高亮关键字
在Windows8商店应用开发中,要让ListView中让指定的关键字高亮,就如下图所示的那样..输入一个z,ListView自动把首字母是z的字全部高亮了,下面我来说说这到底是怎么做到的。
我们来分析一下这个过程,首先要把z为首字母的汉字找出来,然后让这些汉字在ListView中高亮,并且要让ListView行中不同的关键字高亮。过程大概是这样的。
1、找出所有的汉字首字母
public static string GetPinyinCode(string unicodeString) { int i = 0; ushort key = 0; string strResult = string.Empty; Encoding unicode = Encoding.Unicode; Encoding gbk = Encoding.GetEncoding("GBK"); byte[] unicodeBytes = unicode.GetBytes(unicodeString); byte[] gbkBytes = Encoding.Convert(unicode, gbk, unicodeBytes); while (i < gbkBytes.Length) { if (gbkBytes[i] <= 127) { strResult = strResult + (char)gbkBytes[i]; i++; } #region else { key = (ushort)(gbkBytes[i] * 256 + gbkBytes[i + 1]); if (key >= '\uB0A1' && key <= '\uB0C4') { strResult = strResult + "A"; } else if (key >= '\uB0C5' && key <= '\uB2C0') { strResult = strResult + "B"; } else if (key >= '\uB2C1' && key <= '\uB4ED') { strResult = strResult + "C"; } else if (key >= '\uB4EE' && key <= '\uB6E9') { strResult = strResult + "D"; } else if (key >= '\uB6EA' && key <= '\uB7A1') { strResult = strResult + "E"; } else if (key >= '\uB7A2' && key <= '\uB8C0') { strResult = strResult + "F"; } else if (key >= '\uB8C1' && key <= '\uB9FD') { strResult = strResult + "G"; } else if (key >= '\uB9FE' && key <= '\uBBF6') { strResult = strResult + "H"; } else if (key >= '\uBBF7' && key <= '\uBFA5') { strResult = strResult + "J"; } else if (key >= '\uBFA6' && key <= '\uC0AB') { strResult = strResult + "K"; } else if (key >= '\uC0AC' && key <= '\uC2E7') { strResult = strResult + "L"; } else if (key >= '\uC2E8' && key <= '\uC4C2') { strResult = strResult + "M"; } else if (key >= '\uC4C3' && key <= '\uC5B5') { strResult = strResult + "N"; } else if (key >= '\uC5B6' && key <= '\uC5BD') { strResult = strResult + "O"; } else if (key >= '\uC5BE' && key <= '\uC6D9') { strResult = strResult + "P"; } else if (key >= '\uC6DA' && key <= '\uC8BA') { strResult = strResult + "Q"; } else if (key >= '\uC8BB' && key <= '\uC8F5') { strResult = strResult + "R"; } else if (key >= '\uC8F6' && key <= '\uCBF9') { strResult = strResult + "S"; } else if (key >= '\uCBFA' && key <= '\uCDD9') { strResult = strResult + "T"; } else if (key >= '\uCDDA' && key <= '\uCEF3') { strResult = strResult + "W"; } else if (key >= '\uCEF4' && key <= '\uD188') { strResult = strResult + "X"; } else if (key >= '\uD1B9' && key <= '\uD4D0') { strResult = strResult + "Y"; } else if (key >= '\uD4D1' && key <= '\uD7F9') { strResult = strResult + "Z"; } else { strResult = strResult + "?"; } i = i + 2; } #endregion } return strResult; }
2、筛选出高亮关键字,代码大致如下
List<DeliveryItem> list = new List<DeliveryItem>(); foreach (var item in App.CompanyCollection) { var pinyin = Helper.GetPinyinCode(item.DisplayName).ToLower(); int index = pinyin.IndexOf(query); if (index >= 0)//item.Alias.Contains(tb.Text) { DeliveryItem temp = item; temp.LightName = temp.DisplayName.Substring(index, query.Length); list.Add(temp); } else if (item.DisplayName.Contains(tb.Text)) { DeliveryItem temp = item; temp.LightName = query; list.Add(temp); } }
3、构建ListView我们这里需要用到一个控件HighlightingTextBlock,这是Silverlight时代的一个控件,我把它翻译成了适合Windows8商店应用的控件
using System; using System.Collections.Generic; using System.Windows; using Windows.UI; using Windows.UI.Text; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Documents; using Windows.UI.Xaml.Media; namespace Express.Controls { public partial class HighlightingTextBlock : Control { /// <summary> /// The name of the TextBlock part. /// </summary> private string TextBlockName = "Text"; /// <summary> /// Gets or sets the text block reference. /// </summary> private TextBlock TextBlock { get; set; } /// <summary> /// Gets or sets the inlines list. /// </summary> private List<Inline> Inlines { get; set; } #region public string Text /// <summary> /// Gets or sets the contents of the TextBox. /// </summary> public string Text { get { return GetValue(TextProperty) as string; } set { SetValue(TextProperty, value); } } /// <summary> /// Identifies the Text dependency property. /// </summary> public static readonly DependencyProperty TextProperty = DependencyProperty.Register( "Text", typeof(string), typeof(HighlightingTextBlock), new PropertyMetadata("", OnTextPropertyChanged)); /// <summary> /// TextProperty property changed handler. /// </summary> /// <param name="d">AutoCompleteBox that changed its Text.</param> /// <param name="e">Event arguments.</param> private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { HighlightingTextBlock source = d as HighlightingTextBlock; if (source.TextBlock != null) { while (source.TextBlock.Inlines.Count > 0) { source.TextBlock.Inlines.RemoveAt(0); } string value = e.NewValue as string; source.Inlines = new List<Inline>(); if (value != null) { for (int i = 0; i < value.Length; i++) { Inline run = new Run { Text = value[i].ToString() }; source.TextBlock.Inlines.Add(run); source.Inlines.Add(run); } source.ApplyHighlighting(); } } } #endregion public string Text #region public string HighlightText /// <summary> /// Gets or sets the highlighted text. /// </summary> public string HighlightText { get { return GetValue(HighlightTextProperty) as string; } set { SetValue(HighlightTextProperty, value); } } /// <summary> /// Identifies the HighlightText dependency property. /// </summary> public static readonly DependencyProperty HighlightTextProperty = DependencyProperty.Register( "HighlightText", typeof(string), typeof(HighlightingTextBlock), new PropertyMetadata("", OnHighlightTextPropertyChanged)); /// <summary> /// HighlightText property changed handler. /// </summary> /// <param name="d">AutoCompleteBox that changed its HighlightText.</param> /// <param name="e">Event arguments.</param> private static void OnHighlightTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { HighlightingTextBlock source = d as HighlightingTextBlock; source.ApplyHighlighting(); } #endregion public string HighlightText #region public Brush HighlightBrush /// <summary> /// Gets or sets the highlight brush. /// </summary> public Brush HighlightBrush { get { return GetValue(HighlightBrushProperty) as Brush; } set { SetValue(HighlightBrushProperty, value); } } /// <summary> /// Identifies the HighlightBrush dependency property. /// </summary> public static readonly DependencyProperty HighlightBrushProperty = DependencyProperty.Register( "HighlightBrush", typeof(Brush), typeof(HighlightingTextBlock), new PropertyMetadata(new SolidColorBrush(Colors.BlueViolet), OnHighlightBrushPropertyChanged)); /// <summary> /// HighlightBrushProperty property changed handler. /// </summary> /// <param name="d">HighlightingTextBlock that changed its HighlightBrush.</param> /// <param name="e">Event arguments.</param> private static void OnHighlightBrushPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { HighlightingTextBlock source = d as HighlightingTextBlock; source.ApplyHighlighting(); } #endregion public Brush HighlightBrush #region public FontWeight HighlightFontWeight /// <summary> /// Gets or sets the font weight used on highlighted text. /// </summary> public FontWeight HighlightFontWeight { get { return (FontWeight)GetValue(HighlightFontWeightProperty); } set { SetValue(HighlightFontWeightProperty, value); } } /// <summary> /// Identifies the HighlightFontWeight dependency property. /// </summary> public static readonly DependencyProperty HighlightFontWeightProperty = DependencyProperty.Register( "HighlightFontWeight", typeof(FontWeight), typeof(HighlightingTextBlock), new PropertyMetadata(FontWeights.Normal, OnHighlightFontWeightPropertyChanged)); /// <summary> /// HighlightFontWeightProperty property changed handler. /// </summary> /// <param name="d">HighlightingTextBlock that changed its HighlightFontWeight.</param> /// <param name="e">Event arguments.</param> private static void OnHighlightFontWeightPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { HighlightingTextBlock source = d as HighlightingTextBlock; FontWeight value = (FontWeight)e.NewValue; } #endregion public FontWeight HighlightFontWeight /// <summary> /// Initializes a new HighlightingTextBlock class. /// </summary> public HighlightingTextBlock() { DefaultStyleKey = typeof(HighlightingTextBlock); Loaded += OnLoaded; } /// <summary> /// Loaded method handler. /// </summary> /// <param name="sender">The loaded event.</param> /// <param name="e">The event data.</param> private void OnLoaded(object sender, RoutedEventArgs e) { OnApplyTemplate(); } /// <summary> /// Override the apply template handler. /// </summary> protected override void OnApplyTemplate() { base.OnApplyTemplate(); // Grab the template part TextBlock = GetTemplateChild(TextBlockName) as TextBlock; // Re-apply the text value string text = Text; Text = null; Text = text; } /// <summary> /// Apply the visual highlighting. /// </summary> private void ApplyHighlighting() { if (Inlines == null) { return; } string text = Text ?? string.Empty; string highlight = HighlightText ?? string.Empty; StringComparison compare = StringComparison.OrdinalIgnoreCase; int cur = 0; while (cur < text.Length) { int i = highlight.Length == 0 ? -1 : text.IndexOf(highlight, cur, compare); i = i < 0 ? text.Length : i; // Clear while (cur < i && cur < text.Length) { Inlines[cur].Foreground = Foreground; Inlines[cur].FontWeight = FontWeight; cur++; } // Highlight int start = cur; while (cur < start + highlight.Length && cur < text.Length) { Inlines[cur].Foreground = HighlightBrush; Inlines[cur].FontWeight = HighlightFontWeight; cur++; } } } } }
这是一个模版化控件,我们还需要在Generic.xaml里面添加下面代码
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:contorls="using:Express.Controls" xmlns:local="using:Express"> <Style TargetType="contorls:HighlightingTextBlock"> <Setter Property="HighlightBrush" Value="Blue" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="contorls:HighlightingTextBlock"> <TextBlock x:Name="Text" /> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>
下面就很简单了,构建一个ListView,代码大致如下
<ListView Margin="10,70,0,0" BorderBrush="Black" ItemContainerStyle="{StaticResource ListDetailItem}" HorizontalAlignment="Left" ItemsSource="{Binding FilterList, Mode=TwoWay}" > <Interactivity:Interaction.Triggers> <Interactivity:EventTrigger EventName="Loaded"> <Actions:CallMethodAction TargetObject="{Binding Main, Source={StaticResource Locator}}" MethodName="GridView_Loaded" /> </Interactivity:EventTrigger> <Interactivity:EventTrigger EventName="SelectionChanged"> <Actions:CallMethodAction TargetObject="{Binding Main, Source={StaticResource Locator}}" MethodName="FilteredSelectionChanged" /> </Interactivity:EventTrigger> </Interactivity:Interaction.Triggers> <ListView.ItemTemplate> <DataTemplate> <contorls:HighlightingTextBlock VerticalAlignment="Center" Margin="9,0,0,0" HighlightText="{Binding LightName}" Text="{Binding DisplayName}" HighlightBrush="#3db0da"/> </DataTemplate> </ListView.ItemTemplate> </ListView>
这时候筛选出的ListView只要绑定筛选出的列表就会高亮相关的关键字了。
代码大致如上所示,因为是我程序摘抄出来的,有些部分大家需要手动修改一下,我主要说的是思路,希望大家动手后会更深刻,欢迎留言讨论。