今天和大家探讨下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