Exercise 1: Understanding how a Windows 8 Metro Grid Application Works
 

Download the Windows Azure SDK and Tools - To do these posts, absolutely necessary

 

How to provide cloud-based, JSON data to Windows 8 Metro Grid Applications - Part 1 http://blogs.msdn.com/b/brunoterkaly/archive/2012/06/12/how-to-provide-cloud-based-json-data-to-windows-8-metro-grid-applications.aspx
How to provide cloud-based, JSON data to Windows 8 Metro Grid Applications - Part 2 http://blogs.msdn.com/b/brunoterkaly/archive/2012/06/14/how-to-provide-cloud-based-json-data-to-windows-8-metro-grid-applications-part-2.aspx
How to provide cloud-based, JSON data to Windows 8 Metro Grid Applications - Part 3 http://blogs.msdn.com/b/brunoterkaly/archive/2012/06/15/how-to-provide-cloud-based-json-data-to-windows-8-metro-grid-applications-part-3.aspx
How to provide cloud-based, JSON data to Windows 8 Metro Grid Applications - Part 4 http://blogs.msdn.com/b/brunoterkaly/archive/2012/06/17/how-to-provide-cloud-based-json-data-to-windows-8-metro-grid-applications-part-3-windows-azure-cloud.aspx
Source Code


This post will focus on the data model used by this type of application. We need to understand how data is modeled if we plan to architect a cloud-based back-end.

The next few screens will talk a lot about SampleDataGroup and SampleDataItem objects. These are the core data objects used by a Windows 8 Metro Grid Application.


Exercise 1: Task 1 - Creating the starter application with File/New with Visual Studio 2012 RC

The following steps illustrate what is needed to create the starter application.

z233xj0a

  1. Start Visual Studio 2012 RC.
  2. Select File, New Project
  3. Choose “Grid App (XAML)
  4. Provide a name.
    • Warning if you are using your own namespace, be sure when you copy my code you make the appropriate changes.
      • Your namespaces will be off
  5. I recommend sticking with FastMotorcycle



This is the running version of a File/New Metro Grid Application.

Take note of the “groups” and the “items”

3xqavk01

  1. Notice there are 3 groups (more if you scroll to the right)
    • Group: Title 1
      • This group has many items
    • Group: Title 2
      • This group has many items
    • Group: Title 3
      • This group has many items

Exercise 1: Task 2 - Understanding the files generated (Solution Explorer)

There are 2 core things to notice: (1) SampleDataSource.cs – is where we learn about the needed data model. (2) The 3 XAML files (described below) provide the needed user interface.

ge4saw2y
  1. The core files in a Windows 8 Metro Grid Style Application
    • These files where generated by Visual Studio 2012
      • NOTE: You won’t see motorcycles on your version
        • That is the version we will build in the next post or 2.
        • We will need to add that branding later
  2. What is important to notice is the 3 files:
    • GroupDetailPage.xaml
      • Gives details about a group. In this case, the group can be “Sport Bikes” or “Exotic Bikes”
    • GroupedItemsPage.xaml
      • Shows Groups and Items.
      • This is the initial page seen by users
      • You can navigate to the group or to an individual item from here
    • ItemDetailPage.xaml
      • Provides details about and individual item. In this case, it is about an individual motorcycle.



Exercise 1: Task 3 - The core files in a Windows 8 Metro Grid Style Application

The object model needed to support a Windows 8 Metro Grid application is visible below. Common sense dictates that when we create the server-side software, we will need to somehow model this object model on both ends (client and server).

ylzq1izj

  1. The things to notice is: (1) there are 3 classes total, one is a base class (2) there is a one to many relationship
  2. There are 3 classes:
    • SampleDataCommon
    • SampleDataItem
    • SampleDataGroup
  3. One SampleDataGroup contains many SampleDataItem objects. Most of the lists of “things” in this object model is expressed as a ObservableCollection<T>. This data structure provides a convenient eventing model (currently being ignored) so that we can notice edits or changes in the related data objects.
    • See the collection _items
  4. A SampleDataItem has 2 things
    • Content to display for an individual SampleDataItem
    • A group (SampleDataGroup).
      • Each individual SampleDataItem points to its parent.
  5. There is a base class
    • It is SampleDataCommon. It inherits from BindableBase. This provides support as follows:
      • public abstract class BindableBase : INotifyPropertyChanged
      • It provides support for Multicast events, resulting from property change notifications
  6. There are two derived classes from SampleDataCommon:
    • SampleDataItem
    • SampleDataGroup
  7. There are important relationships here:
    • A group has many items
    • An item always belongs to some group
To summarize, the core files in a Windows 8 Metro Grid Style Application
  1. This object model is used by the user interface.
    • GroupDetailPage.xaml
      • Shows a group with a list of items
    • GroupedItemsPage.xaml
      • Shows both groups and items
    • ItemDetailPage.xaml
      • Shows an individual item
  2. The code below is provided by the framework to simplify working with INotifyPropertyChanged. BindableBase is something we just use and don’t worry about.


CLASS = BindableBase
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
public abstract class BindableBase : INotifyPropertyChanged
{
    /// <SUMMARY>
    /// Multicast event for property change notifications.
    /// </SUMMARY>
    public event PropertyChangedEventHandler PropertyChanged;
  
    /// <SUMMARY>
    /// Checks if a property already matches a desired value.  Sets the property and
    /// notifies listeners only when necessary.
    /// </SUMMARY>
    /// <TYPEPARAM name="T">Type of the property.</TYPEPARAM>
    /// <PARAM name="storage">Reference to a property with both getter and setter.</PARAM>
    /// <PARAM name="value">Desired value for the property.</PARAM>
    /// <PARAM name="propertyName">Name of the property used to notify listeners.  This
    /// value is optional and can be provided automatically when invoked from compilers that
    /// support CallerMemberName.</PARAM>
    /// <RETURNS>True if the value was changed, false if the existing value matched the
    /// desired value.</RETURNS>
    protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] String propertyName = null)
    {
        if (object.Equals(storage, value)) return false;
  
        storage = value;
        this.OnPropertyChanged(propertyName);
        return true;
    }
  
    /// <SUMMARY>
    /// Notifies listeners that a property value has changed.
    /// </SUMMARY>
    /// <PARAM name="propertyName">Name of the property used to notify listeners.  This
    /// value is optional and can be provided automatically when invoked from compilers
    /// that support <SEE cref="CallerMemberNameAttribute" />.</PARAM>
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var eventHandler = this.PropertyChanged;
        if (eventHandler != null)
        {
            eventHandler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Exercise 2: SampleDataCommon, SampleDataItem, SampleDataGroup – the core
This is what we’ll need to really understand inside of SampleDataSource.cs.


5umml5om

  1. The base class is SampleDataCommon
    • It gives us the basic strings in a picture of a motorcycle or group (Sport Bikes, Exotic Bikes)
  2. Note that SampleDataItem has 2 extra fields
    • _content
      • A string that displays the text details of a specific motorcycle
    • _group
      • A SampleDataGroup object, which represents the group to which a SampleDataItem belongs
  3. SampleDataGroup
    1. Contains an array of SampleDataItem objects (_items collection)



Exercise 2: Task 1 - Understanding the relationships

A group has many items and an item has exactly one group

vxgx4lth

  1. The core files in a Windows 8 Metro Grid Style Application
  2. A group has many items
    • SampleDataGroup has an “_items” collection
  3. An item has “content” and a “group
    • Note that a SampleDataItem points back to the group to which it belongs



Exercise 2: Task 2 - Everything goes into _allGroups

You only add SampleDataGroups. SampleDataItem are already part of SampleDataGroups.

11lp54hf

  1. The _allGroups collection is where everything ends up.
  2. The SampleDataGroup should already have its collection of SampleDataItem Objects
  3. Each SampleDataItem will point to its parent (SampleDataGroup)
  4. All this data originates as JSON data, obtained from a Windows Azure (Cloud-based) back-end.
  5. This is the code that populates _allGroups.
  6. The code below is the constructor for SampleDataSource. It  hard codes all the data.
    1. Eventually we will replace all this code with http calls to get JSON data.
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
public SampleDataSource()
{
    String ITEM_CONTENT = String.Format("Item Content: {0}\n\n{0}\n\n{0}\n\n{0}\n\n{0}\n\n{0}\n\n{0}",
                "Curabitur class ...");
  
    var group1 = new SampleDataGroup("Group-1",
            "Group Title: 1",
            "Group Subtitle: 1",
            "Assets/DarkGray.png",
            "Group Description: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus tempor scelerisque lorem in vehicula. Aliquam tincidunt, lacus ut sagittis tristique, turpis massa volutpat augue, eu rutrum ligula ante a ante");
    group1.Items.Add(new SampleDataItem("Group-1-Item-1",
            "Item Title: 1",
            "Item Subtitle: 1",
            "Assets/LightGray.png",
            "Item Description: Pellentesque porta, mauris quis interdum vehicula, urna sapien ultrices velit, nec venenatis dui odio in augue. Cras posuere, enim a cursus convallis, neque turpis malesuada erat, ut adipiscing neque tortor ac erat.",
            ITEM_CONTENT,
            group1));
    this.AllGroups.Add(group1);
  
    // Repeat for all groups. here is for Group 2
    var group2 = new SampleDataGroup("Group-2",
            "Group Title: 2",
            "Group Subtitle: 2",
            "Assets/LightGray.png",
            "Group Description: Lorem ");
    group2.Items.Add(new SampleDataItem("Group-2-Item-1",
            "Item Title: 1",
            "Item Subtitle: 1",
            "Assets/DarkGray.png",
            "Item Description: Pellentesque porta, ",
            ITEM_CONTENT,
            group2));
    this.AllGroups.Add(group2);
  
  
    // Omitted for brevity
}

Exercise 2: Task 3 - The sample project derived from the Grid Template that Visual Studio 2012 RC creates contains hard coded data

The class is called SampleDataSource.

idmohoqv

  1. The constructor adds all the SampleDataGroups and SampleDataItems we discussed previously.

Exercise 3: Understanding how the constructor maps to the user interface.
This is key if we plan to supply our own JSON data instead.  The class SampleDataSource has a constructor that adds test data.

pyi22ua4
  1. You can start to see how the code in the constructor for SampleDataSource maps to specific visible elements in the running application
  2. Our job will be re-factor this code (generated by Visual Studio 2012 when File/New Metro Grid application is chosen)
    • We will instead make a call into Azure Cloud-based RESTful services to retrieve data for the Windows 8 Metro Grid Application.



Let's look at some of the built in classes.
We will take a look SampleDataCommon, SampleDataGroup, SampleDataItem.

CLASS = SampleDataCommon
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
[Windows.Foundation.Metadata.WebHostHidden]
public abstract class SampleDataCommon : FastMotorcycle.Common.BindableBase
{
    private static Uri _baseUri = new Uri("ms-appx:///");
  
    public SampleDataCommon(String uniqueId, String title, String subtitle, String imagePath, String description)
    {
        this._uniqueId = uniqueId;
        this._title = title;
        this._subtitle = subtitle;
        this._description = description;
        this._imagePath = imagePath;
    }
  
    private string _uniqueId = string.Empty;
    public string UniqueId
    {
        get { return this._uniqueId; }
        set { this.SetProperty(ref this._uniqueId, value); }
    }
  
    private string _title = string.Empty;
    public string Title
    {
        get { return this._title; }
        set { this.SetProperty(ref this._title, value); }
    }
  
    private string _subtitle = string.Empty;
    public string Subtitle
    {
        get { return this._subtitle; }
        set { this.SetProperty(ref this._subtitle, value); }
    }
  
    private string _description = string.Empty;
    public string Description
    {
        get { return this._description; }
        set { this.SetProperty(ref this._description, value); }
    }
  
    private ImageSource _image = null;
    private String _imagePath = null;
    public ImageSource Image
    {
        get
        {
            if (this._image == null && this._imagePath != null)
            {
                this._image = new BitmapImage(new Uri(SampleDataCommon._baseUri, this._imagePath));
            }
            return this._image;
        }
  
        set
        {
            this._imagePath = null;
            this.SetProperty(ref this._image, value);
        }
    }
  
    public void SetImage(String path)
    {
        this._image = null;
        this._imagePath = path;
        this.OnPropertyChanged("Image");
    }
}

CLASS = SampleDataGroup
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
public class SampleDataGroup : SampleDataCommon
{
    public SampleDataGroup(String uniqueId, String title, String subtitle, String imagePath, String description)
        : base(uniqueId, title, subtitle, imagePath, description)
    {
    }
  
    private ObservableCollection<SAMPLEDATAITEM> _items = new ObservableCollection<SAMPLEDATAITEM>();
    public ObservableCollection<SAMPLEDATAITEM> Items
    {
        get { return this._items; }
    }
          
    public IEnumerable<SAMPLEDATAITEM> TopItems
    {
        // Provides a subset of the full items collection to bind to from a GroupedItemsPage
        // for two reasons: GridView will not virtualize large items collections, and it
        // improves the user experience when browsing through groups with large numbers of
        // items.
        //
        // A maximum of 12 items are displayed because it results in filled grid columns
        // whether there are 1, 2, 3, 4, or 6 rows displayed
        get { return this._items.Take(12); }
    }
}
CLASS = SampleDataItem
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class SampleDataItem : SampleDataCommon
{
    public SampleDataItem(String uniqueId, String title, String subtitle, String imagePath, String description, String content, SampleDataGroup group)
        : base(uniqueId, title, subtitle, imagePath, description)
    {
        this._content = content;
        this._group = group;
    }
  
    private string _content = string.Empty;
    public string Content
    {
        get { return this._content; }
        set { this.SetProperty(ref this._content, value); }
    }
  
    private SampleDataGroup _group;
    public SampleDataGroup Group
    {
        get { return this._group; }
        set { this.SetProperty(ref this._group, value); }
    }
}

Conclusion: Re-factoring our Windows 8 Metro Grid Application
We will need to call into a RESTful cloud-based, Azure back-end. We will need to eliminate the SampleDataSource.cs and add our own version. We will base our version on the existing version and simply modify it so it is a FastMotorcycle Application, not the basic test project. FastMotorcycle Application will be a Windows 8 Metro Grid Application that makes RESTful calls to get data. To understand the next steps, you need to understand the data structure and layout.

  1. The Windows 8 Metro Grid Application provides amazing built in power. You simply need to provide it a basic parent-child data relationship, and the built in Grid Template Application can manage quite a bit.
  2. You do not need to build much of a user interface as the default one provided works very well.
    • Groups will naturally display a list of items.
    • Items will belong group and the user interface will allow you to seamlessly go back and forth between groups and items.
  3. This blog has covered some basics:
    • How to create a new Metro project in Visual Studio
    • How to work with the structure of the project and the files included
    • How to work with the existing data model in terms of groups and items
  4. The next blog will:
    • Replace SampleDataSource.cs with a new version that makes asynchronous calls to retrieve cloud-hosted JSON data
    • Brand the application by supplying custom imagery for tiles and other elements
    • Consume that JSON data in our application and data-bind it to a ListView control

Download for Azure SDK