(X) Hide this
    • Login
    • Join
      • Say No Bots Generate New Image
        By clicking 'Register' you accept the terms of use .

Windows 8 Metro: Layout, view states and navigation

(2 votes)
Andrea Boschin
>
Andrea Boschin
Joined Nov 17, 2009
Articles:   91
Comments:   9
More Articles
1 comments   /   posted on May 07, 2012
Categories:   Windows 8 , General

The target devices where it is expected Windows 8 to runs are something of really amazing, since it should run from tablet devices of the most various sizes to the the widest monitor.

Dealing with various display sizes and with mobile devices requires new capabilities that go beyond the ones required to run on a simple smartphone. First of all you need to adapt the size of your app to the screen, probably reducing or increasing the amount of content you show to the user. Connected with the use of fingers instead of mouse, it is required you are able to use all available space on the screen, expecially with low resolutions. Finally you have to deal with orientation. It is easy and natural to rotate the screen to best fit the content you are using, as an example using a vertical orientation while reading a page.

All these constraints change the game and have been answered by metro-style application. From the point of view of screen size, you are able to deal with it in different ways, adapting the content or introducing additional elements. You are also able to detect changes in orientation and you can take advantage of the whole screen snapping applications on the side and using a navigation paradigm.

Navigate your apps...

Navigation applications are something you already know for sure. They exists in WPF and in Silverlight but probably you know the benefits of this paradigm from the web that has originally introduced it with the browser. A metro-style application is by default a navigation application, since in the very first rows of code they runs the Window content is injected with a Frame control. There isn't anything preventing you from using something of different from a Frame as main element but if you want to give the better experience to your user this is a one-way street.

   1: protected override void OnLaunched(LaunchActivatedEventArgs args)
   2: {
   3:     // Create a Frame to act navigation context and navigate to the first page
   4:     var rootFrame = new Frame();
   5:     rootFrame.Navigate(typeof(BlankPage));
   6:     
   7:     // Place the frame in the current Window and ensure that it is active
   8:     Window.Current.Content = rootFrame;
   9:     Window.Current.Activate();
  10: }

In these lines, from the default App.xaml.cs file you see how the frame is injected and then the Window activated. Having in you hands the code to initialize the frame is important just because you can wrap the fram itself with some application-wide service like, an example, a wait layer that appears when the application is busy with asynchronous activities.

Inside the Frame you can navigate Page instances. A page of your application directly of indirectly inherits from the Page class so it is a good candidate to be navigated to. Differently from Silverlight you didn't use an Uri to navigate to a page but its Type. This choice comes probably from the fact that metro-style applications does not need to have deep-linking from a web page, so there is not any reason of having a complete Uri.

The Frame control exposes all the methods and properties you may need to perform navigation and to detect navigation state. Here is the main:

Navigate(Type page): Perform navigation to a page. This have also an overload you can use to pass a parameter to the destination page. The parameter is of type object so you can pass complex objects.

GoBack(), GoForward(): There go along the navigation stack, back of forward. Side by side with these methods there are two properties, CanGoBack and CanGoForward used if you reached one end of the stack.

StopLoading(): Stop le loading of a page, e.g. if it is taking longer to load.

CurrentSourcePageType:  The type of the page currently loaded.

Navigated, Navigating, NavigationFailed, NavigationStopped: These events, exposed also as overridable methods on the Page class let you know when something related to navigation happens.

Given that your application is subject to be freezed and/or terminated under particular circumstances, the Frame control provides a way to persist the navigation backstack, so it may be resumed when the application is loaded again. In the example project attached to this article, I wrote a simple code to persist and restore navigation across different sessions. No matter if the application is suspended or terminated, the navigation starts always from the last point where it was interrupted:

   1: private void GoToNext(object sender, RoutedEventArgs e)
   2: {
   3:     this.Frame.Navigate(typeof(FirstPage));
   4:     this.SaveAsync();
   5: }
   6:  
   7: public async void SaveAsync()
   8: {
   9:     Dictionary<string, string> values = new Dictionary<string, string>();
  10:  
  11:     values[Consts.NavigationKey] = this.Frame.GetNavigationState();
  12:  
  13:     if (this.Frame.CurrentSourcePageType != null)
  14:         values[Consts.CurrentKey] = this.Frame.CurrentSourcePageType.FullName;
  15:  
  16:     await Utilities.SaveDictionaryAsync(Consts.FileName, values);
  17: }

This code, inside a page persists the navigation state every time it changes. You have simply to call the SaveAsync methos every time you move across pages, just after the call to the navigation method. It saves the current page and the navigation state using the GetNavigationState() method. Then, in the App.xaml.cs you ar requested to restore the state:

   1: protected override void OnLaunched(LaunchActivatedEventArgs args)
   2: {
   3:     // Create a Frame to act navigation context and navigate to the first page
   4:     var rootFrame = new Frame();
   5:  
   6:     if (args.PreviousExecutionState != ApplicationExecutionState.Running)
   7:         this.LoadAsync(rootFrame, typeof(FirstPage));
   8:  
   9:     // Place the frame in the current Window and ensure that it is active
  10:     Window.Current.Content = rootFrame;
  11:     Window.Current.Activate();
  12: }
  13:  
  14: private async void LoadAsync(Frame frame, Type defaultPage = null)
  15: {
  16:     var values = await Utilities.LoadDictionaryAsync(Consts.FileName);
  17:  
  18:     if (values.ContainsKey(Consts.NavigationKey))
  19:     {
  20:         frame.SetNavigationState((string)values[Consts.NavigationKey]);
  21:  
  22:         if (values.ContainsKey(Consts.CurrentKey))
  23:         {
  24:             Type page = Type.GetType((string)values[Consts.CurrentKey]);
  25:             frame.Navigate(page);
  26:         }
  27:     }
  28:     else if (defaultPage != null)
  29:         frame.Navigate(defaultPage);
  30: }

To restore the navigation it reads the string representing the navigation from the filesystem and use the SetNavigationState method to load it in the frame. Then it navigates again to the last page hit by the user. The result is awesome since the application always remember the entire set of actions made by the user.

As for Silverlight, navigation implies caching. The Page class exposes a NavigationCacheMode property useful to define if your page have to be cached after it is loaded the first time. This means you have to handle your page slight differently. The first time your page ctor will be called and the load event raised. All the following calls omit to call ctor and Load so you have to handle the OnNavigated event to know when the page is loaded again.

Layout and ViewState

Once in front of your empty page, there are a number of options to dispose your content on the page. If you ever used layout controls in Silverlight and WPF, you already know the whole story. Grid, StackPanel and Canvas are still there and they works as you already know.

The real problem with layout in metro-style application comes from two points of view. First of all, applications are requested to go beyond the boundaries of the screen to maximize the space available, and for this aspect there are a set of controls available, but also to handle different size of the screen. The size of the screen can vary from the minimum of 1024x768 (10.6") to huge sizes like 2560x1440. The size of 1366x768 is considered a reference point.

If you try to start the simulator, on the right side you will find a button that opens a menu with a set of resolutions. Playing with this menu may be interesting to understand what it happens at different resolutions. When you are in start menu and change the value between the 10.6" resolutions, you will notice that the actual size of the tiles remains unchanged also if the pixel density drastically increases. What Windows does is to adapt the size of the elements to three steps: 100%, 140% and 180%. if you take 1366x768 corresponding to 100% you can easily calculate that 1920x1080 corresponds to 140% and 2560x1440 to 180%. The reason to operate this automatic scaling is to always have a size good for finger manipulation. If this scale would not applied the size of a tile at the maximum resolution will be too small to be hit accurately from a finger.

This automatic resize is good for vector-based graphics but may be drastically bad for bitmap images. It is the reason why you can use a trick to specify three sizes of every image. If you use a Image tag in XAML, since you specify a fixed name for the image you can create three versions and use a name pattern to let the system load the better for the current resolution:

   1: <Image Source="Assets/image.jpg" Width="100" Height="100" />

So after this create three versions of the image adding "scale-*" between the file name and the extension. Windows automatically loads the better image according with the selected resolution. Here is an example:

  • image.scale-100.jpg
  • image.scale-140.jpg
  • image.scale-180.jpg

While designing the layout of your application there are two strategies you can embrace. You can go for a fixed or adaptive layout. Every choose best fit a specific scenario:

Fixed: While in fixed layout your application will be scaled according with the screen resolution. The trick is to use a ViewBox control to wrap the entire content of the screen so when the resolution increases it is scaled automatically. This scenario is mostly choosed with games and dashboards where the screen does not go outside the screen boundaries.

Adaptive: In this layout, the size of items is fixed (according to pixel density rules) but when the screen il larger the number of items presented increases to fill the empty space left. Handling this layout is most difficult then the other but the common applications requires it.

image

image

23" - 1920x1080

10.6" - 1366x768

According with user actions, an application can assume 4 different state. FullScreenLandscape, Filled, Snapped and FullScreenPortrait. The figure behind shows the states:

image

The application have to support all the states to give an effective experience to the user. To detect the states changes you have to subscribe the ViewStateChanged event on the ApplicationView object. When the event raises the arguments let you know the new state so you have to switch on or off the parts of your application to best fit the available space. The best way to accomplish this task is using the LayoutAwarePage class, created by VisualStudio in the Common folder of the project. This class automatically handles states and map them to VisualStateManager states. Thanks to this mapping you can easily use Blend to edit the page like you are defining the states of a control.

An important argument

In this article I've scratched the surface of layout and navigation. Especially layout is something that needs to be deeply understand to create effective apps, able to give a good experience to the user. I suggesto to read some good MSDN articles:

In the next article I will go depth in the lifetime matter to understand suspension and how to handle this important task.


Subscribe

Comments

  • Rajmohan

    Re: Windows 8 Metro: Layout, view states and navigation


    posted by Rajmohan on Jun 08, 2012 09:58

    Great Article ,Can you provide a article on handling gesture (Swipe) and animations for windows 8.

    Thanks in advance,

    Rajmohan K.

Add Comment

Login to comment:
  *      *       

From this series