Windows Phone开发手记-WinRT下分组拼音的实现
Windows Phone版本號自升入8.1以來,開發者就多了一個選項,開發基于WinRT架構的WP或者Universal Windows App。然而開發框架轉為WinRT后,很多原有的WP8基于Sliverlight框架的控件和方法變得不再有效,這無疑帶來較大的困擾。今天我要講述的就是此類問題中較易出現的列表拼音分組方案,本文基于WinRT架構予以實現,下面附上實現效果圖:
?
解決方案:
在WP8下,Silverlight提供了LongListSelector控件,可以方便的實現以上的拼音分組效果,具體實現方法可以參考以下博文:
http://diaosbook.com/Post/2014/2/22/longlistselector-group-by-py-wp8
但是WP8.1則不然,WinRT框架默認不提供分組控件,唯一的解決辦法是我們使用相關控件自己來實現。我講此方案歸納為SemanticZoom+ListView+GridView+ValueConverter=LongListSelector,不得不說,這樣實現的復雜度遠大于Silverlight框架,但其自定義程度高的優勢也很明顯。
1.數據分組
我們要在正常列表視圖下展示分組的列表,這需要我們提前做好數據的分組,對于這一點,官方提供了多種方案,最簡單的就是給List中每一項都提供Key屬性,這樣處理起來最簡單,但卻十分麻煩,需要我們在數據源里提前設計好Key屬性,所以這里我并不會講述這種分組方法。
我要講述的是通用程度較高的分組方案,不需要在數據源中設計好Key屬性,而是按照正常的方式使用數據源,但是我們會對數據源進行分組處理,最后講分組后的數據綁定到ListView控件,當然,我們的分組處理行為都是在后臺自動處理的。
首先為了ListView控件能夠展示分組數據,需要將它的Itemssource綁定到CollectionViewSource數據源,CollectionViewSource數據源IsGrouped屬性必須設置為True,Source屬性綁定到我們提供的分組數據。
<vm:MainPage_Model x:Name="MainVM" x:Key="DesignVM"/> <CollectionViewSource x:Name="GroupData" x:Key="GroupData" IsSourceGrouped="True" Source="{Binding StartCityGroup, Source={StaticResource DesignVM}}"/>后臺處理:
I. 這里我們創建一個輔助類,參考MSDN的文章方案,我進行了修改適應,實現如下:
//將輸入的數據源進行拼音分組,返回CollectionViewSource可以接受的數據結構public class AlphaKeyGroup<T>:List<T>{const string GlobeGroupKey = "?";public string Key { get; private set; }//public List<T> this { get; private set; }public AlphaKeyGroup(string key){Key = key;}private static List<AlphaKeyGroup<T>> CreateDefaultGroups(CharacterGroupings slg){List<AlphaKeyGroup<T>> list = new List<AlphaKeyGroup<T>>();foreach (CharacterGrouping cg in slg){if (cg.Label == "") continue;else if (cg.Label == "...") { list.Add(new AlphaKeyGroup<T>(GlobeGroupKey)); }elselist.Add(new AlphaKeyGroup<T>(cg.Label));}return list;}public static List<AlphaKeyGroup<T>> CreateGroups(IEnumerable<T> items, Func<T, string> keySelector, bool sort){CharacterGroupings slg = new CharacterGroupings();List<AlphaKeyGroup<T>> list = CreateDefaultGroups(slg);foreach (T item in items){int index = 0;string label = slg.Lookup(keySelector(item));index = list.FindIndex(alphagroupkey => (alphagroupkey.Key.Equals(label, StringComparison.CurrentCulture)));if (index > -1 && index < list.Count) list[index].Add(item);}if (sort){foreach (AlphaKeyGroup<T> group in list){group.Sort((c0, c1) => { return keySelector(c0).CompareTo(keySelector(c1)); });}}return list;}}
?
II. 添加可用于綁定到CollectionViewSource的List<AlphaKeyGroup<City>>屬性,這里的City是自定義數據模型,如下:
//這里的代碼是MVVM-Sidekick框架自動生成的,主要就是第一行的定義代碼public List<AlphaKeyGroup<City>> StartCityGroup{get { return _StartCityGroupLocator(this).Value; }set { _StartCityGroupLocator(this).SetValueAndTryNotify(value); }}#region Property List<AlphaKeyGroup<City>> StartCityGroup Setupprotected Property<List<AlphaKeyGroup<City>>> _StartCityGroup = new Property<List<AlphaKeyGroup<City>>> { LocatorFunc = _StartCityGroupLocator };static Func<BindableBase, ValueContainer<List<AlphaKeyGroup<City>>>> _StartCityGroupLocator = RegisterContainerLocator<List<AlphaKeyGroup<City>>>("StartCityGroup", model => model.Initialize("StartCityGroup", ref model._StartCityGroup, ref _StartCityGroupLocator, _StartCityGroupDefaultValueFactory));static Func<BindableBase, List<AlphaKeyGroup<City>>> _StartCityGroupDefaultValueFactory =model =>{var vm = CastToCurrentType(model);//TODO: Add the logic that produce default value from vm current status.return default(List<AlphaKeyGroup<City>>);};#endregion
III. 給StartCityGrup賦予數據,這里就用到我們的輔助類了,實現如下:
//StartCity是List<City>類型的源數據集合 StartCityGroup = AlphaKeyGroup<City>.CreateGroups(StartCity, (City s) => { return s.Name; }, true);這里因為我們要根據城市名稱拼音分組,所以使用了對應的Name屬性。
2.綁定視圖
還需要設置ListView分組標頭,設置GrupStyle,如下:
<ListView Margin="15,10" x:Name="StartCityList" ItemsSource="{Binding Source={StaticResource GroupData}}" Foreground="Black" Background="White" SelectionChanged="StartCityList_SelectionChanged" ><ListView.GroupStyle><GroupStyle HidesIfEmpty="True"><GroupStyle.HeaderTemplate><DataTemplate><Border Background="{StaticResource PhoneAccentBrush}" BorderBrush="{StaticResource PhoneAccentBrush}" BorderThickness="2" Width="62" Height="62" Margin="0,0,18,0" HorizontalAlignment="Stretch"><TextBlock Text="{Binding Key}" Foreground="{StaticResource PhoneForegroundBrush}" FontSize="48" Padding="6" FontFamily="{StaticResource PhoneFontFamilySemiLight}" HorizontalAlignment="Left" VerticalAlignment="Center"/></Border></DataTemplate></GroupStyle.HeaderTemplate></GroupStyle></ListView.GroupStyle><ListView.ItemTemplate><DataTemplate><StackPanel Orientation="Horizontal"><TextBlock Text="{Binding Name}" FontSize="20"/><TextBlock Margin="10,0,0,0" FontSize="20" Text="{Binding CityCode}"/></StackPanel></DataTemplate></ListView.ItemTemplate></ListView>到了這里,ListView就可以實現拼音分組顯示了。
?
IV.實現分組拼音跳轉
這里就需要使用GridView和SemanticZoom控件,GridView控件用于顯示拼音字母集合,SemanticZoom實現視圖切換,實現代碼如下:
<SemanticZoom Background="White" x:Name="semanticZoom" ViewChangeStarted="SemanticZoom_ViewChangeStarted"><SemanticZoom.ZoomedInView><ListView Margin="15,10" x:Name="StartCityList" ItemsSource="{Binding Source={StaticResource GroupData}}" Foreground="Black" Background="White" SelectionChanged="StartCityList_SelectionChanged" ><ListView.GroupStyle><GroupStyle HidesIfEmpty="True"><GroupStyle.HeaderTemplate><DataTemplate><Border Background="{StaticResource PhoneAccentBrush}" BorderBrush="{StaticResource PhoneAccentBrush}" BorderThickness="2" Width="62" Height="62" Margin="0,0,18,0" HorizontalAlignment="Stretch"><TextBlock Text="{Binding Key}" Foreground="{StaticResource PhoneForegroundBrush}" FontSize="48" Padding="6" FontFamily="{StaticResource PhoneFontFamilySemiLight}" HorizontalAlignment="Left" VerticalAlignment="Center"/></Border></DataTemplate></GroupStyle.HeaderTemplate></GroupStyle></ListView.GroupStyle><ListView.ItemTemplate><DataTemplate><StackPanel Orientation="Horizontal"><TextBlock Text="{Binding Name}" FontSize="20"/><TextBlock Margin="10,0,0,0" FontSize="20" Text="{Binding CityCode}"/></StackPanel></DataTemplate></ListView.ItemTemplate></ListView></SemanticZoom.ZoomedInView><SemanticZoom.ZoomedOutView><!-- 縮放后的跳轉界面 --><GridView x:Name="ZoomGridView" ItemsSource="{Binding View.CollectionGroups ,Source={StaticResource GroupData}}" HorizontalAlignment="Center" Background="Gray" VerticalAlignment="Center"><GridView.ItemTemplate><DataTemplate><Border Background="White" ><Border Margin="2" Width="90" Height="90" HorizontalAlignment="Left" Background="{Binding Group.Count,Converter={StaticResource BackgroundConverter}}"><TextBlock Text="{Binding Group.Key}" Foreground="White" FontSize="48" Padding="6" HorizontalAlignment="Left" VerticalAlignment="Center"/></Border></Border></DataTemplate></GridView.ItemTemplate></GridView></SemanticZoom.ZoomedOutView></SemanticZoom>這里需要注意一下,ListView和GridView使用同一個CollectionViewSource作為數據源時,可以實現自動分組跳轉,不需要多余的代碼。如果不是,則需要使用SemanticZoom控件的ViewChangeCompleted和ViewChangeStarted進行代碼控制實現。
V. 實現分組標頭顏色區分
這里我自定義了一個IValueConverter來進行GridView項顯示顏色的轉化,這里根據綁定分組數據的數量來區分,如果此分組有對應的數據則顯示藍色,如果分組數據為空,則顯示為灰色,實際效果如第二張圖片。
轉換器實現代碼:
class BackgroundConverter:IValueConverter{public object Convert(object value, Type targetType, object parameter, string language){if(value!=null){var count = int.Parse(value.ToString());if (count > 0)return new SolidColorBrush(Windows.UI.Colors.Blue);}return new SolidColorBrush(Windows.UI.Colors.Gray);}public object ConvertBack(object value, Type targetType, object parameter, string language){throw new NotImplementedException();}}?
總結:
WinRT框架的實現拼音分組控件雖然復雜程度大增,但是其功能區的高度可自定義化,無疑是較大的進步,我想微軟會在后續的更新中推出更好的控件或解決方案,希望這篇文章對于開發WinRT框架app的你有所幫助。
?
轉載于:https://www.cnblogs.com/mantgh/p/4049031.html
總結
以上是生活随笔為你收集整理的Windows Phone开发手记-WinRT下分组拼音的实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 声母有几个?韵母呢?
- 下一篇: 稻黄金2号到底效果好不好?