One of the useful controls to use when creating a Windows Store app for Windows 8 is the GridView which can use a VariableSizeWrapGrid to support item templates of varying size. Using this in conjunction with an DataTemplateSelector makes it possible to vary both the size and data template of the items in a GridView. Here is how you do it:
The VariableSizeWrapGrid works with a unit size and you can define whatever unit size you want – each template should be a multiple of that. In your GridView.GroupStyle, you should define the ItemHeight and ItemWidth. Add the spacing between the columns & rows; based on the Microsoft guidelines, the height and width should be layed out on a 20-pixel grid and the spacing should be 10 pixels between each item. So in this case each item would be 200x100 with 10-pixel spacing, so ItemWidth=210 and ItemHeight=110.
<GroupStyle.Panel> <ItemsPanelTemplate> <VariableSizedWrapGrid Orientation="Vertical" Margin="0,0,80,0" ItemHeight="110" ItemWidth="210"/> </ItemsPanelTemplate> </GroupStyle.Panel>
Create Data Templates in a resource file that would be used for each item type. In this case, I have a ProjectItemTemplate and FavoriteProjectItemTemplate in a Xaml resource file included in my App.xaml. The FavoriteProjectItemTemplate shows a Gold Star (xE082 in the Segoe UI Symbol) and additional project information that I only want to load for favorite projects:
<DataTemplate x:Key="ProjectItemTemplate"> <Grid HorizontalAlignment="Left" Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}" Width="200" Height="100"> <StackPanel Margin="5"> <TextBlock Text="{Binding Name}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextStyle}"/> <TextBlock Text="{Binding Description}" Foreground="{StaticResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap"/> <TextBlock Text="{Binding UpdatedAt}" Foreground="{StaticResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap"/> </StackPanel> </Grid> </DataTemplate> <DataTemplate x:Key="FavoriteProjectItemTemplate"> <Grid HorizontalAlignment="Left" Background="{StaticResource ListViewItemOverlayBackgroundThemeBrush}" Width="200" Height="210"> <TextBlock HorizontalAlignment="Right" VerticalAlignment="Top" x:Name="Star" TextWrapping="Wrap" Text="" FontFamily="Segoe UI Symbol" Foreground="Gold" FontSize="24" Margin="0,5,10,0"/> <StackPanel Margin="5"> <TextBlock Text="{Binding Name}" Foreground="{StaticResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextStyle}" Margin="0,0,32,0"/> <TextBlock Text="{Binding Description}" Foreground="{StaticResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap"/> <TextBlock Text="{Binding UpdatedAt}" Foreground="{StaticResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap"/> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Aspects[0].Items.Count}" Style="{StaticResource CaptionTextStyle}"/> <TextBlock Text=" discussions" Style="{StaticResource CaptionTextStyle}"/> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Aspects[1].Items.Count}" Style="{StaticResource CaptionTextStyle}"/> <TextBlock Text=" todos" Style="{StaticResource CaptionTextStyle}"/> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Aspects[2].Items.Count}" Style="{StaticResource CaptionTextStyle}"/> <TextBlock Text=" files" Style="{StaticResource CaptionTextStyle}"/> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Aspects[3].Items.Count}" Style="{StaticResource CaptionTextStyle}"/> <TextBlock Text=" text documents" Style="{StaticResource CaptionTextStyle}"/> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Aspects[4].Items.Count}" Style="{StaticResource CaptionTextStyle}"/> <TextBlock Text=" dates" Style="{StaticResource CaptionTextStyle}"/> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Aspects[5].Items.Count}" Style="{StaticResource CaptionTextStyle}"/> <TextBlock Text=" people" Style="{StaticResource CaptionTextStyle}"/> </StackPanel> </StackPanel> </Grid> </DataTemplate>
The Item Template Selector is called each time a new item template is needed. In this, you should pick the item template and set the number of columns & rows the item should span. In this case if the project.IsStarred is true, then the template would use the FavoriteProjectItemTemplate and set VariableSizedWrapGrid to span 2 rows instead of 1.
public class ProjectDataTemplateSelector : DataTemplateSelector { protected override Windows.UI.Xaml.DataTemplate SelectTemplateCore(object item, Windows.UI.Xaml.DependencyObject container) { var project = item as Project; var uiElement = container as UIElement; if (project.IsStarred) { VariableSizedWrapGrid.SetColumnSpan(uiElement, 1); VariableSizedWrapGrid.SetRowSpan(uiElement, 2); return App.Current.Resources["FavoriteProjectItemTemplate"] as DataTemplate; } VariableSizedWrapGrid.SetColumnSpan(uiElement, 1); VariableSizedWrapGrid.SetRowSpan(uiElement, 1); return App.Current.Resources["ProjectItemTemplate"] as DataTemplate; } }
On the page resources, add an instance of the ItemTemplateSelector and then reference it in the GridView.ItemTemplateSelector=”{StaticResources ProjectTemplateSelector}”
<support:ProjectDataTemplateSelector x:Key="ProjectTemplateSelector"/>
If the selection criteria changes and you need the selector logic to run again, just reset the selector. Thanks to this StackOverflow answer for the assistance here.
var projects = this.selector.SelectedItems.Cast<Project>(); foreach (var project in projects) { project.IsStarred = !project.IsStarred; } var itemTemplateSelector = this.selector.ItemTemplateSelector; this.selector.ItemTemplateSelector = null; this.selector.ItemTemplateSelector = itemTemplateSelector;
Varying the item template and size of items increase the visual interest of your app and can help highlight important differences when standard DataTemplate binding won’t work.