Tamir Dresher

Dealing with page resize in Windows Store Applications using Caliburn.Micro

01 Mar 2015

This post was originally published on 01 Mar 2015 at http://blogs.microsoft.co.il/iblogger/2015/03/01/dealing-with-page-resize-in-windows-store-applications-using-caliburn-micro/

Windows Store Applications allow the user to change the size of the application and change the the layout to e vertical or horizontal.

App that pans horizontally, at fullscreenApp that is taller than it is wide and pans vertically.App at narrow minimum width of 320 pixels.

in order to provide god user experience we want adapt our view to different modes. For instance, showing a grid like view when in Full Horizontal mode and change it a List when we are snapped to side (and look vertical).

The examples and guidelines on how to change your view based on the page layout change are around those option:

  1. In your page XAML write the representation for both mode and change visibility based on the current mode
  2. Use VisualStyleManager in your page and change your controls properties based on the current mode

My coworker Noam Gindi and I felt that this is not ideal and starteted to look for a more elegent way

I wanted to take advantage of Caliburn.Micro View.Context

So what we did was creating a base ResizablePage that knows how to change the View.Context according to the page dimensions. since Caliburn.Micro Binds the ViewModel to the Page it will automatically switch the inner view according to the context.

in our case we set a convention that the the view will be suffixed with “SnapView” or “FullView”

This is the ResizalePage code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
public class ResizablePage : Page
{
 
    public ResizablePage()
    {
        this.Loaded += OnLoaded;
    }
 
    private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
    {
        ApplyTemplate();
        this.Loaded -= OnLoaded;
       
        Caliburn.Micro.View.SetContext(this, GetContext(this.ActualWidth));
        Caliburn.Micro.View.SetModel(this, DataContext);
 
        this.SizeChanged += OnSizeChanged;
    }
 
    private void OnSizeChanged(object sender, SizeChangedEventArgs args)
    {
        Caliburn.Micro.View.SetContext(this, GetContext(args.NewSize.Width));
    }
     
 
    private string GetContext(double width)
    {
        if (width <= 500)
        {
            return GetName()+"SnapView";
        }
         
        return GetName()+"FullView";
    }
 
    private string GetName()
    {
        var type = this.GetType();
 
        string str1 = type.FullName;
        var index = str1.LastIndexOf('.') + 1;
        var str2 = str1.Substring(index, str1.Length - index);
        var str3 = str2.Replace("View", "");
 
        return str3;
    }
}
1
  

and now you simply need to derive your page from it and create the inner view for the two cases mentioned above.