Can someone give me some hints how to accomplish the grouping within a GridView for Metro Apps as shown in the Screenshot below.
I may have a solution. In my projet, I had to create a list of contacts in alphabetic order, like the People app.
I used a GridView (with this sample), a CollectionViewSource and a wrappanel I found in the WinRT XAML Toolkit (you can get with NuGet package or copy/paste the source code). It allow you to put your items in columns.
Example
ViewModel
class ContactListViewModel
{
public ContactListViewModel()
{
ContactSource = new CollectionViewSource();
Contacts = new ObservableCollection<Contact>();
Contacts.Add(new Contact("Gates","Bill"));
Contacts.Add(new Contact("Bush","Georges"));
Contacts.Add(new Contact("Obama","Barack"));
Contacts.Add(new Contact("Hollande","François"));
Contacts.Add(new Contact("Affleck","Ben"));
Contacts.Add(new Contact("Allen","Woody"));
Contacts.Add(new Contact("Hendrix","Jimi"));
Contacts.Add(new Contact("Harrison", "Georges"));
Contacts = new ObservableCollection<Contact>(Contacts.OrderBy(c => c.Name));
ContactSource.Source = GetGroupsByLetter();
ContactSource.IsSourceGrouped = true;
}
#region Contacts
public ObservableCollection<Contact> Contacts
{
get;
protected set;
}
public CollectionViewSource ContactSource
{
get;
protected set;
}
#endregion
internal List<GroupInfoList<object>> GetGroupsByLetter()
{
List<GroupInfoList<object>> groups = new List<GroupInfoList<object>>();
var query = from item in Contacts
orderby ((Contact)item).Name
group item by ((Contact)item).Name[0] into g
select new { GroupName = g.Key, Items = g };
foreach (var g in query)
{
GroupInfoList<object> info = new GroupInfoList<object>();
info.Key = g.GroupName;
foreach (var item in g.Items)
{
info.Add(item);
}
groups.Add(info);
}
return groups;
}
public class GroupInfoList<T> : List<object>
{
public object Key { get; set; }
public new IEnumerator<object> GetEnumerator()
{
return (System.Collections.Generic.IEnumerator<object>)base.GetEnumerator();
}
}
}
View
<DataTemplate x:Key="contactTemplate">
<Grid Width="225" Height="75" Background="#55FFFFFF">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" FontSize="20">
<Run Text="{Binding FirstName}"/>
<Run Text="{Binding Name}"/>
</TextBlock>
<TextBlock Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Left" Text="{Binding Email}" FontSize="13" Foreground="#FFDDDDDD"/>
</Grid>
</Grid>
</DataTemplate>
<DataTemplate x:Key="letterTemplate">
<Grid Margin="5,0,0,5" Width="225">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding Key}" Style="{StaticResource GroupHeaderTextStyle}" VerticalAlignment="Center"/>
<Rectangle Grid.Row="1" Fill="#BBEEEEEE" Height="1" Margin="0,7,0,0"/>
</Grid>
</DataTemplate>
</Page.Resources>
<!--
This grid acts as a root panel for the page that defines two rows:
* Row 0 contains the back button and page title
* Row 1 contains the rest of the page layout
-->
<Grid Style="{StaticResource LayoutRootStyle}">
<Grid.RowDefinitions>
<RowDefinition Height="140"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Back button and page title -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="backButton" Click="GoBack" Style="{StaticResource BackButtonStyle}" Opacity="0"/>
<TextBlock x:Name="pageTitle" Grid.Column="1" Text="Manager" Style="{StaticResource PageHeaderTextStyle}"/>
</Grid>
<GridView Grid.Row="1"
ItemsSource="{Binding Path=ContactSource.View}"
SelectionMode="Multiple"
IsSwipeEnabled="false"
IsItemClickEnabled="True"
Padding="116,10,40,46"
ItemTemplate="{StaticResource contactTemplate}">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<local:WrapPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.GroupStyle>
<GroupStyle HeaderTemplate="{StaticResource letterTemplate}">
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Orientation="Vertical" Margin="0,0,80,0"/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</GridView.GroupStyle>
</GridView>
</Grid>
It can't be done using the default grid view styles.
You may have to use one none-grouped item list and add special items with different item template ...
Sorry
I would add the headers as items to the gridview, and use a TemplateSelector to display the elements the right way...
http://code.msdn.microsoft.com/windowsapps/GroupedGridView-77c59e8e