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.
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