Getting Started with Metro–Repository and Display (p2)

First an update to the previous entry.  Special thanks to David Kean, of Microsoft for pointing out that the HttpClient class exists for the sole purpose to handle web requests, the way I was doing it was outdated.  I actually knew of this class, but mistakenly thought it was WebClient.

Since the last coding adventure I decided to move some code around and work with a more established pattern for accessing my data.  I defined this interface for my repository (just a start).

public interface ITrendRepository
{
     Task<IList> GetTrendLocationsAsync();
     Task<IList> GetAvailableTrendsAsync(IList locs);
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Both of these methods will, potentially, be marked async in their implementations, but you are not allowed to specify it here. It makes sense, because the underlying implementation may not require async capability, Ill explain more in a moment.

I am creating a very simple repository layer here, within which I have two repositories: MockTrendRepository and ActualTrendRepository.  In the Mock version, I am returning hard coded data (I have hit Twitter’s rate limit too much to keep using actual).  In the Actual version, I am hitting Twitter directly.

Coding MockTrendRepository was interesting. I don’t want to show a ton of code, so this is one of the methods:

public async Task<IList> GetTrendLocationsAsync()
{
    return new List
        {
            new TrendLocation
            {
                LocationIds = new int[] {},
                LocationName = "United States"
            },
            new TrendLocation
            {
                LocationIds = new int[] {},
                LocationName = "United Kingdom"
            },
            new TrendLocation
            {
                LocationIds = new int[] {},
                LocationName = "Mexico"
            },
            new TrendLocation
            {
                LocationIds = new int[] {},
                LocationName = "Russia"
            },
        };
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Remember, when you mark a method as async it must return Task, Task, or void.  However, if you look at this method, you can early see I follow that rule with method definition, but the method actually returns a straight List, which is T in the Task declaration.

My explanation for this is, because there is no await method being used, the code is deemed to run synchronously, thus the compiler will understand that it wont need to wrap the method body with Task, so its superfluous in this case. (notice, VS11 Beta, does underline the method in green to indicate you are missing await in the method body; this is not an error.

Making it Metro

So, now we have all of our data, we need to present it to the user.  At the moment this part is still unfinished.  I am currently at the point where my data displays but is not following Metro guidelines, but I figured its good to get starting talking about the GridView control.

If you have seen Metro applications before, you are familiar with seeing a GridView, or a control similar to it.  It allows for Groups which are arranged horizontally under the main title and then rectangular boxes around the individual items in the datasource, this what I am currently looking at now:

MetroScreen

I swear, from all the Microsoft talks, that there is a way to get the appropriate Metro boxes around these items without specifying the template explicitly.

GridView requires a CollectionViewSource as its datasource.  Since we are grouping these items, we set the IsSourceGrouped property true, here is my XAML:

DatasourceDeclare

Understand that CollectionViewSource is a standard .NET class, it is sealed so it cannot be inherited.  In order to bind to this properly, use a standard LINQ statement to group your data by the appropriate key and simple assign it to the resource, the cvs member variable.

var bindingData = from at in availableTrends
                  group at by at.Country into g
                  orderby g.Key
                  select g;

cvs.Source = bindingData;

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

This is different from the previous version of VS11, where you used IGroupInfo interface, this has now been removed as a means to simplify this process.

Setting the GridView Parts

The GridView control has several parts that we care about: ItemsPanel, ItemTemplate, GroupStyle.HeaderTemplate, and GroupStyle.Panel.

ItemsPanel defines what the general layout panel for the control is.  GridView will display groups in a certain way.  Typically, you’ll want a horizontal StackPanel, so the group items are laid out left to right.  This will leverage horizontal scrolling.

     
          <StackPanel Orientation="Horizontal" />
     

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

The ItemTemplate is our old standby, from WPF, for laying out the individual items in the ItemsSource.  This template controls how the individual items look as it they are laid out within the master ItemsPanel.  In this case, it’s a Grid (background LimeGreen) with a TextBlock showing the trend.

<GridView.ItemTemplate>
     <DataTemplate>
          <Grid Height="150" Width="150" Background="LimeGreen">
               <TextBlock Text="{Binding Display}" FontSize="14.667"
                                  FontFamily="Segoe UI" VerticalAlignment="Center"
                                  HorizontalAlignment="Center" />
          </Grid>
     </DataTemplate>
</GridView.ItemTemplate>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

The GroupStyle.HeaderTemplate, as you might expect, defines the template that will render the groups keys.  Make sure you bind whatever the display element is appropriately.  Because I am using IGrouping which defines the property Key of type TKey. Thus, the property that I use for display is Key.

<GroupStyle.HeaderTemplate>
     <DataTemplate>
          <StackPanel Orientation="Vertical">
               <TextBlock Text="{Binding Key}" FontSize="26.667"
                      FontFamily="Segoe UI" />
          </StackPanel>
     </DataTemplate>
</GroupStyle.HeaderTemplate>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

The final template we define is the GroupStyle.Panel which defines the panel used to layout the items in the ItemsSource, recall the ItemTemplate defines what goes on inside this panel, so this will be a single panel definition.

<GroupStyle.Panel>
     <ItemsPanelTemplate>
          <VariableSizedWrapGrid Orientation="Vertical" />
     </ItemsPanelTemplate>
</GroupStyle.Panel>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

One of the additional guidelines for Metro’s approaching to differentiating items in terms of importance is font sizing.

  • Header – Segoe UI – 42pt
  • Sub Header – Segoe UI – 20pt
  • Support – Segoe UI – 11pt
  • Tertiary Text – Segoe UI – 9pt

Typically, either Segoe UI or Helvetica is used as font types in Metro style apps.

Next Steps

So at this point, I have gotten the basics down, but I have bad spacing between the groups.  Plus I am convinced that there is an easier way to create the Metro UI boxes for the items.  I am still researching that aspect.  I also need to create the drill down for the next level.  I am considering a change, so that I show the locations with trends instead of the all the trends.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s