Creating a snap view with XAML in Windows 8 (WinRT)

If you create a new WinRT solution using the Grid or Split Application Template you'll get all the code you need to create a layout aware page that shows a different view when in snap view. If you start of your project using the blank project template, you need to do a little bit more work to get it working.

First you need to change the page to be a layout aware page. LayoutAwarePage is a class provided by the template and is in the Common folder. (Update: In Visual Studio 2012 RC LayoutAwarePage is no longer in the common folder for a blank page project. You need to copy the file from the Grid or Split Application template. The new version also depends on SuspensionManager also in the common folder of those project templates.)

In BlankPage.xaml.cs change:

public sealed partial class BlankPage : Page

to

public sealed partial class BlankPage : LayoutAwarePage

In BlankPage.xaml you need to change a view things:

The main page tag now needs to be a LayoutAwarePage so change it from this:

<Page
    x:Class="Application1.BlankPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Application1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

to

<common:LayoutAwarePage
    x:Name="pageRoot"
    x:Class="Application1.BlankPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Application1"
    xmlns:common="using:Application1.Common"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

Your page is now a layout aware page, so all you need to do is add a visual state manager that will control how things look in each different view. You may choose to show or hide different elements based on the view, or just change some sizes. Either way you include all the elements you want in the page set at the size you want them to be in the standard view. You hide them if you only want them to be visible in the snap view. Here is a simple example of a visual state manager:

<VisualStateManager.VisualStateGroups>
  <VisualStateGroup>
    <VisualState x:Name="FullScreenLandscape" />
    <VisualState x:Name="Filled" />
    <VisualState x:Name="FullScreenPortrait" />
    <VisualState x:Name="Snapped">
      <Storyboard>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="MyListScroller" Storyboard.TargetProperty="Visibility">
          <DiscreteObjectKeyFrame KeyTime="0" Value="Visible" />
        </ObjectAnimationUsingKeyFrames>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="MyGridScroller" Storyboard.TargetProperty="Visibility">
          <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed" />
        </ObjectAnimationUsingKeyFrames>
      </Storyboard>
    </VisualState>
  </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

In this example I have a list view which is initially hidden for snap view and a grid view for my full screen view which I hide for the snap view.

Abdul Rahaman said

OMG OMG! Thanks a lot Richard. I was trying to make the snap view work on my app for over a week but couldn't do it because it was made from a blank page. Now after making changes, it works! Thanks again! :D

Matt said

I'm using the VB version, Any chance in making a VB version of this? I'm so confused... The <Base> is all I have and I'm getting real stressed over it.. I can't seem to figure it out as I'm like 1 day into programming and I need this information to get to my next task! It would be gratefully appreciated!

Using Express 2012 Win8

Patrick said

Thanks a lot for the help! It worked like a charm. One issue I encountered that was probably my fault for mucking around with stuff previously was that I had to change

xmlns:common="using:Application1.Common" to xmlns:common="using:Application1"

I thought I'd share in case anyone else has the same issue. But anyways, thanks!

Richard Garside said

@Patrick you shouldn't change the common namespace mapping in your XAML file. You just need to make sure that LayoutAware page is in the common namespace.

Janice said

I'm confused with this part: <Page x:Class="Application1.BlankPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

my code does not have this reference, there is a <page.Resources> reference, is this what you're referring to?

Janice said

I made the other changes and I'm still getting the following error: Error 1 The name "LayoutAwarePage" does not exist in the namespace "using:ContosoCookbook.Common".

This is so frustrating when I'm trying to learn, I find this language hard to learn, can you recommend a good book with good examples that actually work? Microsoft gives a lot of training, and maybe if I could actually complete a training without a bunch of errors I could get somewhere. geeza

Richard Garside said

@Janice, adding a snap view is more tricky than it should be, even for those of us who've been programming for a while.

The x:class part should match the name of your main XAML page, which might be something like ContosoCookbook.MainPage. Just keep this bit as it was before you changed to using LayoutAwarePage.

As for books. I read Programming Windows 8 by Charles Petzold. It goes into a lot of depth and has good examples, but it might not be the best book for a beginner.

Janice said

Thanks for the help Richard, I will try that.

Janice said

I don't see a main xaml page in this project, by main do you mean literally main.xaml? some projects do have that or just for example GroupDetailPage.xaml as the main page?

Janice said

I still haven't figured this one out but I got it to run using the javascript/html implementation, yippy!!

I will get back to the C# version some other time, working on a deadline

Richard Garside said

@Janice By main XAML page, I mean which ever page you want to add a snap view to. So, if there are multiple pages that you want to add a snap view to you need to make sure they all inherit from LayoutAwarePage.