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 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;
}
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>
<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>
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);
}
Jesse Liberty has three decades of experience writing and delivering software projects. He is the author of 2 dozen books and has been a Distinguished Software Engineer for AT&T and a VP for Information Services for Citibank and a Software Architect for PBS. You can read more on his personal blog or follow him on twitter