Click here to Skip to main content
Click here to Skip to main content

Metro In Motion #5 – SandwichFlow

, 19 May 2011
Rate this:
Please Sign up or sign in to vote.
For the past few months I have been writing a Metro-In-Motion blog series which describes how to recreate some of the fluid effects found in native Windows Phone 7 applications within your own applications. So far I have covered fluid list animations, 'peel' animations, flying titles...

For the past few months I have been writing a Metro-In-Motion blog series which describes how to recreate some of the fluid effects found in native Windows Phone 7 applications within your own applications. So far I have covered fluid list animations, 'peel' animations, flying titles and a 'tilt' effect – and now … I am all out of ideas!

The previous blog posts used a pretty simple little application to demonstrate their functionality, so I thought it might be fun to put these effects together within a more meaningful application. Rather than simply re-hashing an old idea, like a Twitter app, I decided to create something original, something inspiring, something which explores a subject area close to my heart – and stomach. This is how I came up with the (entirely original) SandwichFlow … an application for the sandwich aficionado!!!

SandwichFlow – As good as sandwiches get on a mobile … Brought to you by Team Distraction and ColinDoesIt (AsWell):

Random Points Of Interest

The important bits of this application are covered in the previous Metro-In_motion blog posts, so the following is just a random bunch of things that your might find interesting about this application:

Recipe Thief

The recipes were scraped from the fantastic BBC Food web-pages, which are published in XHTML format, making it easy for me to grab the various component parts of each recipe. The scraped output was saved as an XML file which the application uses to build a view model using Linq to XML:

XDocument doc = XDocument.Parse(xml);
Sandwiches = doc.Descendants("sandwich")
                .Select(el => new Sandwich()
                {
                    Title = el.Attribute("title").Value,
                    Id = id++,
                    Keywords = el.Descendants("keyword")
                                  .Select(l => Regex.Replace(l.Value, @"\b(\w)", m => m.Value.ToUpper()))
                                  .ToList(),
                    Ingredients = el.Descendants("ingredient")
                                    .Select(l => l.Value)
                                    .ToList(),
                    Instructions = el.Descendants("instruction")
                                    .Select(l => new InstructionStep()
                                    {
                                        Text = l.Value,
                                        Step = l.ElementsBeforeSelf().Count() + 1
                                    })
                                    .ToList()

                })
                .ToList();

Jump then slide

The front-page of the application uses the JumpList control I wrote a few months back, with DataTemplates supplied for rending recipes or keywords that have the MetroInMotion.AnimationLevel property set on various elements so that they slide gracefully as the pivot control is animated from one item to the next:

<DataTemplate x:Key="SandwichTemplate">
  <StackPanel Orientation="Vertical"
              Margin="0,5,0,5"
              mim:MetroInMotion.Tilt="3">
    <TextBlock  Text="{Binding Title}"
                mim:MetroInMotion.AnimationLevel="1"
                x:Name="Title"
                Foreground="Black"
                FontSize="{StaticResource PhoneFontSizeLarge}"/>
    <TextBlock Text="{Binding KeywordSummary}"
                mim:MetroInMotion.AnimationLevel="2"
                FontSize="{StaticResource PhoneFontSizeNormal}"
                Foreground="#888"/>
  </StackPanel>
</DataTemplate>

Bring it back

I originally added the background image to each page, then I realised a better place to put this is the application frame:

<Style x:Key="mainFrameStyle"
    TargetType="phone:PhoneApplicationFrame">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="phone:PhoneApplicationFrame">
        <Grid Background="White">
          <!-- background image -->
          <Image Source="background.jpg"
                HorizontalAlignment="Stretch"
                VerticalAlignment="Stretch"/>
          <Border x:Name="ClientArea"
                  BorderBrush="{TemplateBinding BorderBrush}"
                  BorderThickness="{TemplateBinding BorderThickness}"
                  Background="{TemplateBinding Background}"
                  HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
                  VerticalAlignment="{TemplateBinding VerticalAlignment}">
            <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}"
                              Content="{TemplateBinding Content}"
                              HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                              Margin="{TemplateBinding Padding}"
                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
          </Border>
        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

The application frame remains throughout the application lifetime, it hosts the currently displayed page. I have a feeling that the application frame is a little under-used. Rather than adding your application title to each page, why not add it to the frame?

The same but different

The code to find similar sandwiches uses an interesting Linq method which I have not used before, Intersect. It is always good to learn something new!

    // locate related sandwiches
    foreach (var sandwich in Sandwiches)
    {
        sandwich.Similar = Sandwiches.Where(s => s != sandwich)
                            .Select(s =>
                              new
                              {
                                  Sandwich = s,
                                  Score = KeywordCorrelation(s.Keywords, sandwich.Keywords)
                              })
                            .OrderBy(s => s.Score).Reverse()
                            .Take(5)
                            .Select(s => s.Sandwich)
                            .ToList();
    }
private double KeywordCorrelation(List<string> keywordsOne, List<string> keywordsTwo)
{
    var commonKeywords = keywordsOne.Intersect(keywordsTwo);
    var allKeywords = keywordsOne.Union(keywordsTwo).Distinct();
    return (double)commonKeywords.Count() / (double)allKeywords.Count();
}

The KeywordCorrelation methods finds the number of keywords that both sandwiches have in common, then divides this by the distinct collection of keywords for both sandwiches. Yummy.

Slippery Ingredients

When you view a recipe, the ingredients slide in from the right. I didn't really have time to find images for all of the ingredients on the web, so each recipe has the ingredients of my favourite – the cheese and pickle sandwich. Each ingredient slides in using a storyboard, with their BeginTime staggered:

<Image Source="tom.png"
        Margin="150,70,0,0"
        mim:MetroInMotion.AnimationLevel="2">
  <Image.RenderTransform>
    <TranslateTransform x:Name="tomTrans"
                          X="400"/>
  </Image.RenderTransform>
  <Image.Triggers>
    <EventTrigger RoutedEvent="Image.Loaded">
      <BeginStoryboard>
        <Storyboard BeginTime="00:00:0.2">
          <DoubleAnimation Duration="00:00:0.7"
                            Storyboard.TargetName="tomTrans" 
                            Storyboard.TargetProperty="X" 
                            From="400" To="0">
            <DoubleAnimation.EasingFunction>
              <SineEase EasingMode="EaseOut"/>
            </DoubleAnimation.EasingFunction>
          </DoubleAnimation>
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Image.Triggers>
</Image>

They also have the MetroInMotion.AnimationLevel attached property set so that they slide with the pivot control.

You can grab the code here: SandwichFlow.zip

Regards, Colin E.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Colin Eberhardt
Architect Scott Logic
United Kingdom United Kingdom
I am CTO at ShinobiControls, a team of iOS developers who are carefully crafting iOS charts, grids and controls for making your applications awesome.
 
I am a Technical Architect for Visiblox which have developed the world's fastest WPF / Silverlight and WP7 charts.
 
I am also a Technical Evangelist at Scott Logic, a provider of bespoke financial software and consultancy for the retail and investment banking, stockbroking, asset management and hedge fund communities.
 
Visit my blog - Colin Eberhardt's Adventures in .NET.
 
Follow me on Twitter - @ColinEberhardt
 
-
Follow on   Twitter   Google+

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web02 | 2.8.140814.1 | Last Updated 19 May 2011
Article Copyright 2011 by Colin Eberhardt
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid