Grouping GridView on Windows 8

It took me a few minutes to get the grouping working on the GridView on my Windows 8 app. I’m sharing what I did just so others can get it working sooner and go by the rest of their work.

In VS 2012, I added a Grouped Items Page to my Windows 8 application project.

image

By default, the template will add some sample data, so you can just run it to see how things look. Let’s see what it takes to show our custom data on the page. I’ll stat with the data source.

   1:  public class Team
   2:  {
   3:      public Team(string uniqueId, string teamName, string member, string manager, 
   4:                  int experienceInYears)
   5:      {
   6:          UniqueId = uniqueId;
   7:          TeamName = teamName;
   8:          Member = member;
   9:          Manager = manager;
  10:          ExperienceInYears = experienceInYears;
  11:      }
  12:   
  13:      public string UniqueId { get; set; }
  14:      public string TeamName { get; set; }
  15:      public string Member { get; set; }
  16:      public string Manager { get; set; }
  17:      public int ExperienceInYears { get; set; }
  18:  }
  19:   
  20:  public class TeamDataSource
  21:  {
  22:      public List<Team> Teams { get; set; }
  23:   
  24:      public TeamDataSource()
  25:      {
  26:          Teams = new List<Team>();
  27:   
  28:          Team team = new Team("devTeam", "Dev Team", "Arun", "Vijay", 9);
  29:          Teams.Add(team);
  30:          team = new Team("devTeam", "Dev Team", "Sanjeev", "Vijay", 10);
  31:          Teams.Add(team);
  32:          team = new Team("devTeam", "Dev Team", "Giri", "Sita", 3);
  33:          Teams.Add(team);
  34:          team = new Team("devTeam", "Dev Team", "Dinesh", "Vijay", 6); 
  35:          Teams.Add(team);
  36:   
  37:          team = new Team("testTeam", "Testing Team", "John", "Rubin", 7);
  38:          Teams.Add(team);
  39:          team = new Team("testTeam", "Testing Team", "Vamsi", "Rubin", 5);
  40:          Teams.Add(team);
  41:          team = new Team("testTeam", "Testing Team", "Priyoj", "Babu", 2);
  42:          Teams.Add(team);
  43:      }
  44:  }

I'm going to use the CollectionViewSource in order to bind data to my grid view.

   1:  <CollectionViewSource
   2:      x:Name="groupedItemsViewSource"
   3:      Source="{Binding Groups}"
   4:      IsSourceGrouped="true"/>

My grid view has a very basic design. I have stripped it to the bare minimum, so u don’t see any margins, foreground styles or anything like that.

   1:  <GridView
   2:      x:Name="itemGridView"
   3:      ItemsSource="{Binding Source={StaticResource groupedItemsViewSource}}">
   4:      <GridView.ItemTemplate>
   5:          <DataTemplate>
   6:              <Grid HorizontalAlignment="Left" Width="140" Height="140">
   7:                  <StackPanel Orientation="Vertical">
   8:                      <TextBlock Text="{Binding Member}" />
   9:                      <TextBlock>
  10:                          <Run Text="Exp: "/>
  11:                          <Run Text="{Binding ExperienceInYears}" />
  12:                          <Run Text=" yrs"/>
  13:                      </TextBlock>
  14:                      <TextBlock>
  15:                           <Run Text="Manager: "/>
  16:                           <Run Text="{Binding Manager}" />
  17:                      </TextBlock>
  18:                  </StackPanel>
  19:              </Grid>
  20:          </DataTemplate>
  21:      </GridView.ItemTemplate>
  22:      <GridView.ItemsPanel>
  23:          <ItemsPanelTemplate>
  24:              <VirtualizingStackPanel Orientation="Horizontal"/>
  25:          </ItemsPanelTemplate>
  26:      </GridView.ItemsPanel>
  27:      <GridView.GroupStyle>
  28:          <GroupStyle>
  29:              <GroupStyle.HeaderTemplate>
  30:                  <DataTemplate>
  31:                      <Grid>
  32:                          <TextBlock Text="{Binding Key}" />
  33:                      </Grid>
  34:                  </DataTemplate>
  35:              </GroupStyle.HeaderTemplate>
  36:              <GroupStyle.Panel>
  37:                  <ItemsPanelTemplate>
  38:                      <VariableSizedWrapGrid Orientation="Vertical" />
  39:                  </ItemsPanelTemplate>
  40:              </GroupStyle.Panel>
  41:          </GroupStyle>
  42:      </GridView.GroupStyle>
  43:  </GridView>

The lines 31-33 is the grid that defines the header of the grid view and the lines 6-19 render the item itself. Line 32 says that we’ll be binding the ‘Key’ element as the header element. There is no ‘Key’ property in our data source classes. We’ll see that from the code below, where the binding actually happens.

   1:  protected override void LoadState(Object navigationParameter, 
   2:                                    Dictionary<String, Object> pageState)
   3:  {
   4:      TeamDataSource teamlist = new TeamDataSource();
   5:      var teamGroups = teamlist.Teams.GroupBy(team=>team.TeamName)
   6:                                     .OrderBy(team => team.Key.ToString());
   7:   
   8:      DefaultViewModel["Groups"] = teamGroups;
   9:  }

The ‘Key’ is actually added by grouping. It basically means that the data is being ‘pivoted’ on some key, which in this case is the TeamMember property.

image

The benefit of doing it this ways is that we can group by some combination of the properties. We can always say, I’d like to group it by team name AND manager.

   1:  var teamGroups = teamlist.Teams.GroupBy(team => team.TeamName + "-" + team.Manager)
   2:                                 .OrderBy(team => team.Key.ToString());

image

You may have observed that our data source is pretty flat and it might not be the case all the time. Data usually comes in a hierarchical fashion. Let’s take that example as well.

   1:  public class Team
   2:  {
   3:      public Team(String member, String manager, 
   4:                  int experienceInYears)
   5:      {
   6:          Member = member;
   7:          Manager = manager;
   8:          ExperienceInYears = experienceInYears;
   9:      }
  10:   
  11:      public string Member { get; set; }
  12:      public string Manager { get; set; }
  13:      public int ExperienceInYears { get; set; }
  14:  }
  15:   
  16:   
  17:  public class TeamDetail
  18:  {
  19:      public string TeamName { get; set; }
  20:      public List<Team> Teams { get; set; }
  21:  }
  22:   
  23:  public class TeamDetailsSource
  24:  {
  25:      public List<TeamDetail> TeamDetails { get; set; }
  26:   
  27:      public TeamDetailsSource()
  28:      {
  29:          TeamDetails = new List<TeamDetail>();
  30:          TeamDetail teamDetail = new TeamDetail{ TeamName = "Devs team" };
  31:          TeamDetails.Add(teamDetail);
  32:   
  33:          teamDetail.Teams = new List<Team>();
  34:          Team team = new Team("Arun", "Vijay", 9);
  35:          teamDetail.Teams.Add(team);
  36:          team = new Team("Sanjeev", "Vijay", 10);
  37:          teamDetail.Teams.Add(team);
  38:          team = new Team("Giri", "Sita", 3);
  39:          teamDetail.Teams.Add(team);
  40:          team = new Team("Dinesh", "Vijay", 6);
  41:          teamDetail.Teams.Add(team);
  42:   
  43:          teamDetail = new TeamDetail { TeamName = "Test team" };
  44:          teamDetail.Teams = new List<Team>();
  45:          TeamDetails.Add(teamDetail);
  46:          team = new Team("John", "Rubin", 7);
  47:          teamDetail.Teams.Add(team);
  48:          team = new Team("Vamsi", "Rubin", 5);
  49:          teamDetail.Teams.Add(team);
  50:          team = new Team("Priyoj", "Babu", 2);
  51:          teamDetail.Teams.Add(team);
  52:      }
  53:  }

This is a typical hierarchical collection that I have.

The way I’ll be binding my data is by just initializing the collection.

   1:  var teamGroups = new TeamDetailsSource().TeamDetails;
   2:   
   3:  DefaultViewModel["Groups"] = teamGroups;

There is one other change that we’ll have to do to our CollectionViewSource. We need to provide the path for the collection where the items exist. This is done by setting the ItemsPath property. The ItemDetails class as a property called Teams which is what needs to be passed to the ItemsPath setting.

   1:  <CollectionViewSource
   2:      x:Name="groupedItemsViewSource"
   3:      Source="{Binding Groups}"
   4:      IsSourceGrouped="true"
   5:      ItemsPath="Teams"/>

image

IT JUST HAS TO WORK!

3 Comments

  • The tiles doesn't appear and I wrote this code without changing anything

  • Hey

    Thanks for posting this. Very helpful. But I wanted to understand one thing. Do I add the code in the .xaml.cs file corresponding to my .xaml file? This doesn't look like a C# code.. looks closer to Java.

    Would you be able to let me know this so I can proceed with my application development. I am trying to add a Grid View on my existing app in the MainPage itself.

    I have just a couple of buttons as of now. I'll now be adding the GridView to it.

  • @@Leo,

    Please go through the article and the code Visual Studio creates by default. It does a lot of wiring up for us. So all you need to do is to create your view (how you want to display your data), initialize your own data model and pass it for data binding.

    Yes, you write your code in the MainPage.xaml.cs file and trust me, it is C# code!

    Arun

Comments have been disabled for this content.