今天和大家探討下GridView如何綁定分組數據的例子。
要實現分組綁定數據主要兩個步驟:
1、創建創建CollectionViewSource並且綁定(這里可以使用兩種類型的數據作為數據源,一種使用Linq,另一種使用的時集合中包含集合數據);
2、設置GroupStyle的相關屬性和樣式。
第一步:創建集合數據源
public sealed partial class Group : Page { CollectionViewSource cvsActivities;//, cvsProjects; DateTime startDate;//一個界定時間 public Group() { this.InitializeComponent(); } protected override void OnNavigatedTo(NavigationEventArgs e) { DateTime.TryParse("1/1/2014", out startDate);//初始化一個界定時間 cvsActivities = new CollectionViewSource(); InitActivities(); //cvsActivities.Source = InitActivities(); cvsActivities.IsSourceGrouped = true; listView.ItemsSource = cvsActivities.View; CollectionViewSource cvsProjects = new CollectionViewSource(); cvsProjects.Source = InitProjects(); cvsProjects.IsSourceGrouped = true; cvsProjects.ItemsPath = new PropertyPath("Activities");//這里需要指定每組數據子項目的路徑 gridView.ItemsSource = cvsProjects.View; } private void InitActivities() { List<Activity> Activities = new List<Activity>(); Activities.Add(new Activity() { Name = "Activity 1", Complete = true, DueDate = startDate.AddDays(4), Project = "Project 1" }); Activities.Add(new Activity() { Name = "Activity 2", Complete = true, DueDate = startDate.AddDays(5), Project = "Project 1" }); Activities.Add(new Activity() { Name = "Activity 3", Complete = false, DueDate = startDate.AddDays(7), Project = "Project 1" }); Activities.Add(new Activity() { Name = "Activity 4", Complete = false, DueDate = startDate.AddDays(9), Project = "Project 1" }); Activities.Add(new Activity() { Name = "Activity 5", Complete = false, DueDate = startDate.AddDays(14), Project = "Project 1" }); Activities.Add(new Activity() { Name = "Activity A", Complete = true, DueDate = startDate.AddDays(2), Project = "Project 2" }); Activities.Add(new Activity() { Name = "Activity B", Complete = false, DueDate = startDate.AddDays(4), Project = "Project 2" }); Activities.Add(new Activity() { Name = "Activity C", Complete = true, DueDate = startDate.AddDays(5), Project = "Project 2" }); Activities.Add(new Activity() { Name = "Activity D", Complete = false, DueDate = startDate.AddDays(9), Project = "Project 2" }); Activities.Add(new Activity() { Name = "Activity E", Complete = false, DueDate = startDate.AddDays(18), Project = "Project 2" }); //自己創建分組 使用Linq查詢的分組數據 var result = from act in Activities group act by act.Project into grp orderby grp.Key select grp; cvsActivities.Source = result; //return result.ToList<Activity>();//這個方法不能使用 } private List<Project> InitProjects() { List<Project> Projects = new List<Project>(); //第一個Project Project newProject = new Project(); newProject.Name = "Project 1"; newProject.Activities.Add(new Activity() { Name = "Activity 1", Complete = true, DueDate = startDate.AddDays(4) }); newProject.Activities.Add(new Activity() { Name = "Activity 2", Complete = true, DueDate = startDate.AddDays(5) }); newProject.Activities.Add(new Activity() { Name = "Activity 3", Complete = false, DueDate = startDate.AddDays(7) }); newProject.Activities.Add(new Activity() { Name = "Activity 4", Complete = false, DueDate = startDate.AddDays(9) }); newProject.Activities.Add(new Activity() { Name = "Activity 5", Complete = false, DueDate = startDate.AddDays(14) }); Projects.Add(newProject); //第二個Project newProject = new Project(); newProject.Name = "Project 2"; newProject.Activities.Add(new Activity() { Name = "Activity A", Complete = true, DueDate = startDate.AddDays(2) }); newProject.Activities.Add(new Activity() { Name = "Activity B", Complete = false, DueDate = startDate.AddDays(3) }); newProject.Activities.Add(new Activity() { Name = "Activity C", Complete = true, DueDate = startDate.AddDays(5) }); newProject.Activities.Add(new Activity() { Name = "Activity D", Complete = false, DueDate = startDate.AddDays(9) }); newProject.Activities.Add(new Activity() { Name = "Activity E", Complete = false, DueDate = startDate.AddDays(18) }); Projects.Add(newProject); //第三個Project沒有子項 newProject = new Project(); newProject.Name = "Project 3"; Projects.Add(newProject); return Projects; //這里每一個子項目都包含一個子項集合數據 //cvsProjects.Source = Projects; //cvsProjects.ItemsPath = new PropertyPath("Activities"); } } public class Activity { public string Name { get; set; } public DateTime DueDate { get; set; } public bool Complete { get; set; } public string Project { get; set; } } public class Project { public Project() { Activities = new ObservableCollection<Activity>(); } public string Name { get; set; } public ObservableCollection<Activity> Activities { get; private set; } } public class ListGroupStyleSelector : GroupStyleSelector { protected override GroupStyle SelectGroupStyleCore(object group, uint level) { // Group g = new Group(); return (GroupStyle)App.Current.Resources["listViewGroupStyle"];//(GroupStyle)g.Resources["listViewGroupStyle"]; //(GroupStyle)App.Current.Resources["listViewGroupStyle"]; } } }
下面講解下代碼和我遇到的問題:
a、里面有兩個類Activity和Project;Activity類主要包括一些基本屬性,所以在InitActivities方法里面使用的時Linq查詢返回的集合數據,Project類里面還包含一個集合數據;
在InitActivities方法中我本來想直接返回List<Activity>,但是當我調用ToList方法的時候報錯了;貌似在Win8中不能用還是什么,大家指點下;
b、在創建CollectionViewSource的時候主要注意問題的我們必須設置IsSourceGrouped為true、並且必須制定ItemsPath(Linq查詢的可以不需要);在設置數據源的時候我們需要用的是View屬性(例: listView.ItemsSource = cvsActivities.View)
第二步:設置GroupStyle
<Page x:Class="Win8AppControls.ListViewAndGridView.GridView.Group" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Win8AppControls.ListViewAndGridView.GridView" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Page.Resources> <local:ListGroupStyleSelector x:Key="listGroupStyle"/> </Page.Resources> <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> <StackPanel Margin="100 50 100 50" Orientation="Horizontal"> <ListView Name="listView" ItemTemplate="{StaticResource listViewItemTemplate}" GroupStyleSelector="{StaticResource listGroupStyle}" Width="320"/> <GridView Name="gridView" Margin="20 0"> <!--設置每一個組里子項目的樣式,相當於沒有分組前的每一個Item的模板--> <GridView.ItemTemplate> <DataTemplate> <StackPanel Margin="20"> <TextBlock Text="{Binding Name}" FontWeight="Bold" Style="{StaticResource ItemTextStyle}"/> <TextBlock Text="{Binding DueDate}" TextWrapping="NoWrap" Style="{StaticResource BodyTextStyle}" /> <CheckBox Content="Complete" IsChecked="{Binding Complete}" IsEnabled="False"/> </StackPanel> </DataTemplate> </GridView.ItemTemplate> <!--設置每個組的布局方式--> <GridView.ItemsPanel> <ItemsPanelTemplate> <VirtualizingStackPanel Orientation="Horizontal"/> </ItemsPanelTemplate> </GridView.ItemsPanel> <!--設置分組模版樣式包括Head和Container--> <GridView.GroupStyle> <!--如果組數據為空則自動隱藏--> <GroupStyle HidesIfEmpty="True"> <!--設置頭模板--> <GroupStyle.HeaderTemplate> <DataTemplate> <Grid Background="LightGray" Margin="0"> <!--這里綁定的是分組數據的屬性--> <TextBlock Text='{Binding Name}' Foreground="Black" Margin="30" Style="{StaticResource HeaderTextStyle}"/> </Grid> </DataTemplate> </GroupStyle.HeaderTemplate> <GroupStyle.ContainerStyle> <!--設置每一組的樣式--> <Style TargetType="GroupItem"> <Setter Property="MinWidth" Value="600"/> <Setter Property="BorderBrush" Value="DarkGray"/> <Setter Property="BorderThickness" Value="2"/> <Setter Property="Margin" Value="3,0"/> </Style> </GroupStyle.ContainerStyle> <!--設置每組里面每一個子項的布局方式--> <GroupStyle.Panel> <ItemsPanelTemplate> <VariableSizedWrapGrid/> </ItemsPanelTemplate> </GroupStyle.Panel> </GroupStyle> </GridView.GroupStyle> </GridView> </StackPanel> </Grid> </Page>
在XAML頁面我們需要設置:
GridView.ItemTemplate:每一個組里子項目的樣式,相當於沒有分組前的每一個Item的模板
GridView.ItemsPanel:每個組的布局方式
GridView.GroupStyle:分組模版樣式包括Head和Container
GroupStyle.HeaderTemplate:頭模板
GroupStyle.ContainerStyle:每一組的樣式
GroupStyle.Panel:每組里面每一個子項的布局方式
在這里遇到問題是:我將ListView的GroupStyleSelector寫在當前頁面通過當前頁面實例去獲取資源的時候會產生一個StackOverFlow異常,放在App.xaml頁面就不會,請指點下;
運行結果
在運行結果上面為什么會出想默認就選擇了第一項;難道是使用了CollectionViewSource的緣故嗎?因為我沒有設置默認選擇,求指點。
詳細代碼大家可以參考MSDN