GridView is one of the most powerful out-of-the-box controls in Windows 8, but fully understanding how to use it is not necessarily trivial. The complexity, I believe, comes because GridViews are often used to hold groups of collections, rather than simple collections. The GridView template assumes that it will be displaying groups of collections of items, and this can make working with the GridView, initially, more complex than it would otherwise be.
Gridview shares all the same methods, properties and events with ListView; all of which they inherit from their base classes. The two controls are nearly identical; the key difference being that ListView is used to scroll items vertically, while GridView is used to scroll items horizontally.
Getting Started
Getting started with GridView is nearly trivial, as I showed in this article. Today, we’ll take a look at a more realistic use of GridView however, one that displays groups of collections, and that is not trivial.
Let’s assume that our data consists of people, with each person having a first name, a last name and a city.
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string City { get; set; }
We’d like to display these people in a GridView, but organized (grouped) by city. The trick is to create a Group class that will allow you to have a key on which you’ll group the people (in this case city) and a list of people who match that key,
public class Group<TKey, TItem>
{
public TKey Key { get; set; }
public IList<TItem> Items { get; set; }
}
To generate your initial (ungrouped) list of people you might go out to a service, or read in XML, or in our case, you might generate names and cities at random. To do so, we’ll have three arrays,
private static readonly string[] firstNames = { "Adam", "Bob", "Carl", "David", "Edgar", "Frank", "George", "Harry", "Isaac", "Jesse", "Ken", "Larry" };
private static readonly string[] lastNames = { "Aaronson", "Bobson", "Carlson", "Davidson", "Enstwhile", "Ferguson", "Harrison", "Isaacson", "Jackson", "Kennelworth", "Levine" };
private static readonly string[] cities = { "Boston", "New York", "LA", "San Francisco", "Phoenix", "San Jose", "Cincinnati", "Bellevue" };
And you’ll need a method to generate a given number of people randomly mixing names and cities,
public static IEnumerable<Person> CreatePeople(int count)
{
var people = new List<Person>();
var r = new Random();
for (int i = 0; i < count; i++)
{
var p = new Person()
{
FirstName = firstNames[r.Next(firstNames.Length)],
LastName = lastNames[r.Next(lastNames.Length)],
City = cities[r.Next(cities.Length)]
};
people.Add(p);
}
return people;
}
Creating the GridView
Let’s turn now to the view. In MainPage.xaml you’ll add a GridView control which will bind its itemsSource to a CollectionViewSource.
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<GridView x:Name="myGridView"
ItemsSource="{Binding Source={StaticResource cvs}}">
<Page.Resources>
<CollectionViewSource x:Name="cvs"
IsSourceGrouped="True"
ItemsPath="Items" />
</Page.Resources>
Within the GridView itself we want to determine how the groups will be organized, and for that we use the ItemsControl.ItemsPanel,
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="GridViewItem">
<Setter Property="HorizontalContentAlignment"
Value="Left" />
<Setter Property="Padding"
Value="5" />
</Style>
</ItemsControl.ItemContainerStyle>
Next we want to determine how each group will be laid out. This consists of two templates: one for the header and one for the items themselves. The Headertemplate will, in our case, display the city which is, you’ll remember the Key property in the Group
<ItemsControl.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Key}"
FontSize="26.67" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Orientation="Vertical"
ItemWidth="220" />
</ItemsPanelTemplate>
</GroupStyle.Panel>
The Supporting Code
In the code behind I generate the 200 people into a list and then use a LINQ statement to obtain a list of Group objects, which I set as the source for the CollectionViewSource,
people = Person.CreatePeople( 200 ).ToList();
groupedPeople = ( from person in people
group person by person.City into g
orderby g.Key
select new Group<object, Person>
{
Key = g.Key.ToString(),
Items = g.ToList()
} ).ToList();
cvs.Source = groupedPeople;
public override string ToString()
{
return string.Format("{0} {1} ({2})", FirstName, LastName, City);
}
The net effect is the gridview shown in the figure at the top of this posting.