<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>.NET by Example</title><link>http://dotnetbyexample.blogspot.com/</link><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/blogspot/dotnetbyexample" /><description>This blog attempts to be a collection of .NET how-to examples - things that may take forever to find out, especially for the beginner. &lt;br&gt;I see it as my way to return something to the .NET community in exchange for what I learned from it.</description><language>en</language><managingEditor>noreply@blogger.com (Joost van Schaik)</managingEditor><lastBuildDate>Sun, 29 Jan 2012 08:36:37 PST</lastBuildDate><generator>Blogger</generator><atom:id xmlns:atom="http://www.w3.org/2005/Atom">tag:blogger.com,1999:blog-5295746446529817470</atom:id><openSearch:totalResults xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/">100</openSearch:totalResults><openSearch:startIndex xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/">1</openSearch:startIndex><openSearch:itemsPerPage xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/">25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/blogspot/dotnetbyexample" /><feedburner:info uri="blogspot/dotnetbyexample" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><title>Templating a XAML CheckBox to a thumbs-up/down control using Expression Blend</title><link>http://feedproxy.google.com/~r/blogspot/dotnetbyexample/~3/DJwMxfckeh0/templating-xaml-checkbox-to-thumbs.html</link><category>WP7NL</category><category>XAML</category><category>wpdev</category><category>WP7</category><category>Blend</category><author>noreply@blogger.com (Joost van Schaik)</author><pubDate>Sun, 29 Jan 2012 04:15:00 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5295746446529817470.post-8931341196290208521</guid><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/GWbsK1vm-in1KN4hcwL9ETCcBzQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/GWbsK1vm-in1KN4hcwL9ETCcBzQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/GWbsK1vm-in1KN4hcwL9ETCcBzQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/GWbsK1vm-in1KN4hcwL9ETCcBzQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#333333" size="4"&gt;Preface&lt;/font&gt;&lt;/p&gt; &lt;p&gt;The checkbox has been been around in the Graphical User Interface for as long as I can remember &lt;em&gt;doing&lt;/em&gt; GUI – since the early 90’s I guess. You know what, let’s make that “it’s been around for&lt;em&gt; longer than I care to remember”&lt;/em&gt; ;). For my newest &lt;a href="http://www.microsoft.com/windowsphone/" target="_blank"&gt;Windows Phone&lt;/a&gt; project I wanted something different. In stead of boring old&amp;nbsp; &lt;/p&gt; &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-OAhxfT317GU/TyU4GomU0hI/AAAAAAAAHE0/vIF1NoDXOsw/s1600-h/checkbox2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="checkbox" border="0" alt="checkbox" align="left" src="http://lh4.ggpht.com/-JA2sVHPDJh8/TyU4HE5aW0I/AAAAAAAAHE4/3103kPz5n24/checkbox_thumb.png?imgmax=800" width="99" height="46"&gt;&lt;/a&gt;&amp;nbsp; &lt;p&gt;&amp;nbsp; &lt;p&gt;I wanted something like this:  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-py9n2zpwLwc/TyU4Hjihc-I/AAAAAAAAHFE/Gv6zoUtoono/s1600-h/thumbsupdown2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="thumbsupdown" border="0" alt="thumbsupdown" src="http://lh6.ggpht.com/-jdwKwMC4l8Y/TyU4IXAHPFI/AAAAAAAAHFM/zdcBq-Y-RP4/thumbsupdown_thumb.png?imgmax=800" width="99" height="46"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Turns out you can do this in pure XAML. And almost entirely in Expression Blend, too. I could just post the XAML and be done with it, but I like to document the track I took, not only to educate you, but also to remember &lt;em&gt;myself&lt;/em&gt; how the hell I got here in the first place ;-). &lt;/p&gt; &lt;p&gt;&lt;font size="4"&gt;Setting the stage&lt;/font&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Open Visual Studio 2010  &lt;li&gt;Create a new Windows Phone 7 (7.1 of course!) project,  &lt;li&gt;Make a folder “icons”&lt;a href="http://lh6.ggpht.com/-jTLcNBC-9qY/TyU4Ja9_n2I/AAAAAAAAHFU/HwZ618iY8LI/s1600-h/build-actions1.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="build actions" border="0" alt="build actions" align="right" src="http://lh5.ggpht.com/-g-8lfLVhBBE/TyU4J-tEnhI/AAAAAAAAHFY/sMnn1bAnSgI/build-actions_thumb1.png?imgmax=800" width="275" height="114"&gt;&lt;/a&gt;  &lt;li&gt;Download &lt;a href="http://www.schaikweb.net/dotnetbyexample/thumbsup.png" target="_blank"&gt;this image&lt;/a&gt; to your computer  &lt;li&gt;Paste it in the “icons” folder in Visual Studio  &lt;li&gt;Double check the image’s properties, they should be as showed to the right.  &lt;li&gt;Save the project &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;font size="4"&gt;Creating style and control template&lt;/font&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Open the project in Expression blend  &lt;li&gt;Put one (or more, for all I care) CheckBoxes on the phone page. &lt;!--EndFragment--&gt;&lt;/li&gt;&lt;/ul&gt; &lt;ul&gt; &lt;li&gt;Select one of them, then click in the main Blend menu “Object/Edit Style/Create Empty”.  &lt;li&gt;In the dialog that follows, enter “Thumbupdowncheckboxstyle” for a name and select “Application” under “Define in”  &lt;li&gt;You will get a screen with a single CheckBox. Right click it, select “Edit template/Create Empty”.  &lt;li&gt;In the dialog that follows, enter “Thumbupdowncheckboxtemplate” for a name and select “Application” under “Define in”&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;First thing you will notice is that the selected CheckBox completely disappears from your design surface. That’s because basically you have replaced the entire look for the CheckBox by an &lt;em&gt;empty template&lt;/em&gt;, which is essentially well, pretty empty indeed. It only contains a grid, and even that’s gonna go.&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Delete the Grid  &lt;li&gt;Add a Rectangle to the template by double clicking on the Rectangle button from the Assets toolbar on the left&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;This is a good moment to turn on Split View in the designer, because that shows you what the designer is actually doing. Right-click the rectangle in the Objects and Timeline panel, and select “View XAML”. At this point you will see only this:&lt;/p&gt;&lt;pre style="font-size: 11px"&gt;&amp;lt;Application.Resources&amp;gt;

  &amp;lt;ControlTemplate x:Key="Thumbupdowncheckboxtemplate" TargetType="CheckBox"&amp;gt;
    &amp;lt;Rectangle Fill="#FFF4F4F5" Stroke="Black"/&amp;gt;
  &amp;lt;/ControlTemplate&amp;gt;

  &amp;lt;Style x:Key="Thumbupdowncheckboxstyle" TargetType="CheckBox"&amp;gt;
    &amp;lt;Setter Property="Template" Value="{StaticResource Thumbupdowncheckboxtemplate}"/&amp;gt;
  &amp;lt;/Style&amp;gt;

&amp;lt;/Application.Resources&amp;gt;
&lt;/pre&gt;
&lt;p&gt;And the design surface will only show a horizontal white rectangle with a black border.&lt;/p&gt;
&lt;p&gt;&lt;font size="4"&gt;Default control size&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lh4.ggpht.com/-c9nkiSQVOVk/TyU4KaFtMcI/AAAAAAAAHFg/g1cVf4Q6CV4/s1600-h/Resources2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Resources" border="0" alt="Resources" align="right" src="http://lh6.ggpht.com/-tLZKOqR_zIA/TyU4KkdyK2I/AAAAAAAAHFo/3KyX6YI0g7I/Resources_thumb.png?imgmax=800" width="244" height="119"&gt;&lt;/a&gt;First and foremost, set the default size of your control. To get this done, look right top, select the Resources tab and expand App.Xaml. Then proceed as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Right-click Thumbupdowncheckboxstyle 
&lt;li&gt;Select “Edit” 
&lt;li&gt;Select the “Properties” tab left of the “Resources” tab 
&lt;li&gt;Locate the “Width” and “Height” fields and enter 40 for both. &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Your XAML now should look like this:&lt;/p&gt;&lt;pre style="font-size: 11px"&gt;&amp;lt;Application.Resources&amp;gt;

  &amp;lt;ControlTemplate x:Key="Thumbupdowncheckboxtemplate" TargetType="CheckBox"&amp;gt;
    &amp;lt;Rectangle Fill="#FFF4F4F5" Stroke="Black"/&amp;gt;
  &amp;lt;/ControlTemplate&amp;gt;

  &amp;lt;Style x:Key="Thumbupdowncheckboxstyle" TargetType="CheckBox"&amp;gt;
    &amp;lt;Setter Property="Template" Value="{StaticResource Thumbupdowncheckboxtemplate}"/&amp;gt;
    &amp;lt;Setter Property="Width" Value="40"/&amp;gt;
    &amp;lt;Setter Property="Height" Value="40"/&amp;gt;
  &amp;lt;/Style&amp;gt;

&amp;lt;/Application.Resources&amp;gt;&lt;/pre&gt;
&lt;p&gt;&lt;font size="4"&gt;Propagate default size to template &lt;/font&gt;&lt;/p&gt;
&lt;p&gt;Now go back to editing the Control template again:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Once again go to the “Resources” tab left top 
&lt;li&gt;Right-click Thumbupdowncheckboxtemplate 
&lt;li&gt;Select “Edit”. 
&lt;li&gt;Select the Rectangle and Click the tab “Properties” top left again&lt;a href="http://lh6.ggpht.com/-1pp-sVCRZxg/TyU4LQg_dII/AAAAAAAAHF0/Y2aGxAaiUZ8/s1600-h/width2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="width" border="0" alt="width" align="right" src="http://lh6.ggpht.com/-lVbRDW9VrCI/TyU4MaYPhtI/AAAAAAAAHF4/ar3sQQu03Wc/width_thumb.png?imgmax=800" width="244" height="52"&gt;&lt;/a&gt; 
&lt;li&gt;Click the little square all the way to the right behind the field “Width” 
&lt;li&gt;This will popup a menu. Select “Template Binding/Width” 
&lt;li&gt;Click the little square behind “Height” and Select “Template Binding/Height”&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;This will set the width and height of the rectangle to the full width and height of the control. If the user does not set a specific width and height, the values in the default Setters (both 40) will be used. XAML at this point:&lt;/p&gt;&lt;pre style="font-size: 11px"&gt;&amp;lt;Application.Resources&amp;gt;

  &amp;lt;ControlTemplate x:Key="Thumbupdowncheckboxtemplate" TargetType="CheckBox"&amp;gt;
    &amp;lt;Rectangle Fill="#FFF4F4F5" Stroke="Black" Width="{TemplateBinding Width}" 
    Height="{TemplateBinding Height}"/&amp;gt;
  &amp;lt;/ControlTemplate&amp;gt;

  &amp;lt;Style x:Key="Thumbupdowncheckboxstyle" TargetType="CheckBox"&amp;gt;
    &amp;lt;Setter Property="Template" Value="{StaticResource Thumbupdowncheckboxtemplate}"/&amp;gt;
    &amp;lt;Setter Property="Width" Value="40"/&amp;gt;
    &amp;lt;Setter Property="Height" Value="40"/&amp;gt;
  &amp;lt;/Style&amp;gt;

&amp;lt;/Application.Resources&amp;gt;&lt;/pre&gt;
&lt;p&gt;&lt;font size="4"&gt;Initial colors&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;Next steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://lh4.ggpht.com/-3hrIVpbfKqQ/TyU4Mw0jBrI/AAAAAAAAHGE/wM1NsPeHYog/s1600-h/Color5.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Color" border="0" alt="Color" align="right" src="http://lh5.ggpht.com/-ZUgffVwBn8g/TyU4NexSWjI/AAAAAAAAHGM/8Gf9vwkZQEo/Color_thumb1.png?imgmax=800" width="244" height="186"&gt;&lt;/a&gt;Click the white white rectangle behind “Fill” 
&lt;li&gt;Don’t bother to select a color: simply type in “Green” in the text box and Blend will make a pretty hex string of it ;-) 
&lt;li&gt;After that, click the little white square behind “Stroke” 
&lt;li&gt;From the popup-menu, select “Reset”&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;The design surface now shows a&lt;em&gt; green&lt;/em&gt; rectangle. Oh wow ;-) but bear with me, we will get there in the end. Your XAML should now look like this:&lt;/p&gt;&lt;pre style="font-size: 11px"&gt;&amp;lt;Application.Resources&amp;gt;

  &amp;lt;ControlTemplate x:Key="Thumbupdowncheckboxtemplate" TargetType="CheckBox"&amp;gt;
    &amp;lt;Rectangle Fill="Green" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}"/&amp;gt;
  &amp;lt;/ControlTemplate&amp;gt;

  &amp;lt;Style x:Key="Thumbupdowncheckboxstyle" TargetType="CheckBox"&amp;gt;
    &amp;lt;Setter Property="Template" Value="{StaticResource Thumbupdowncheckboxtemplate}"/&amp;gt;
    &amp;lt;Setter Property="Width" Value="40"/&amp;gt;
    &amp;lt;Setter Property="Height" Value="40"/&amp;gt;
  &amp;lt;/Style&amp;gt;

&amp;lt;/Application.Resources&amp;gt;&lt;/pre&gt;
&lt;p&gt;&lt;font size="4"&gt;Including the image as an ‘opacity mask’&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lh6.ggpht.com/-35uIjvrdzOM/TyU4OPVgNgI/AAAAAAAAHGQ/fXrl0BGEN0U/s1600-h/Opacity10.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Opacity" border="0" alt="Opacity" align="right" src="http://lh5.ggpht.com/-orawiu50t0Q/TyU4OvzZKfI/AAAAAAAAHGY/0PmAn2OOv_w/Opacity_thumb4.png?imgmax=800" width="222" height="240"&gt;&lt;/a&gt;Blend’s greatest asset – it’s enormous capabilities – unfortunately is also sometimes its Achilles’ heel: there’s a bewildering set of options that’s not always easy to find your way in. Fortunately, at the top of the Properties there’s a Search box that helps you find that hard-to-find-options. Which is extremely helpful – if you happen to know what to look for ;-). In this case: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Enter “Opacity” in the Search box 
&lt;li&gt;Click “No Brush” 
&lt;li&gt;Select “Tile Brush” – that’s the 2nd icon from the left 
&lt;li&gt;That produces a drop-down where you can select “icons/thumbsup.png”&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;your XAML should now look like this:&lt;/p&gt;&lt;pre style="font-size: 11px"&gt;&amp;lt;Application.Resources&amp;gt;

  &amp;lt;ControlTemplate x:Key="Thumbupdowncheckboxtemplate" TargetType="CheckBox"&amp;gt;
  &amp;lt;Rectangle Fill="Green" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}"&amp;gt;
    &amp;lt;Rectangle.OpacityMask&amp;gt;
    &amp;lt;ImageBrush Stretch="Fill" ImageSource="icons/thumbsup.png"/&amp;gt;
    &amp;lt;/Rectangle.OpacityMask&amp;gt;
  &amp;lt;/Rectangle&amp;gt;
  &amp;lt;/ControlTemplate&amp;gt;

  &amp;lt;Style x:Key="Thumbupdowncheckboxstyle" TargetType="CheckBox"&amp;gt;
  &amp;lt;Setter Property="Template" Value="{StaticResource Thumbupdowncheckboxtemplate}"/&amp;gt;
  &amp;lt;Setter Property="Width" Value="40"/&amp;gt;
  &amp;lt;Setter Property="Height" Value="40"/&amp;gt;
  &amp;lt;/Style&amp;gt;

&amp;lt;/Application.Resources&amp;gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://lh3.ggpht.com/-XJS9682X1yk/TyU4PFAxyxI/AAAAAAAAHGg/P6tErFm4SwM/s1600-h/desing212.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="desing2" border="0" alt="desing2" align="right" src="http://lh4.ggpht.com/-ZbcJfOuYgs4/TyU4PjoQh5I/AAAAAAAAHGo/fB1DRTfd_Eg/desing2_thumb8.png?imgmax=800" width="117" height="89"&gt;&lt;/a&gt;&lt;a href="http://lh3.ggpht.com/-_cAq2bXpJCk/TyU4QFgRBDI/AAAAAAAAHGw/hEf9ar2puU8/s1600-h/design7.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px 5px 0px 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="design" border="0" alt="design" align="left" src="http://lh5.ggpht.com/-WSV848k2hQw/TyU4Qtt1VSI/AAAAAAAAHG8/SslfL-vaRQA/design_thumb3.png?imgmax=800" width="123" height="88"&gt;&lt;/a&gt;Your design surface should now looks like to the image to the left, which is kinda crummy. You can use the little triangle on the right bottom, and the two little lines on the right and the bottom, to resize the &lt;em&gt;design&lt;/em&gt; surface. This will have no effect on the control template itself, it will make just make it look better (see right image) . &lt;/p&gt;
&lt;p&gt;You can also manually add the attributes &lt;strong&gt;d:DesignWidth="75"&lt;/strong&gt; and &lt;strong&gt;d:DesignHeight="75"&lt;/strong&gt; to the Rectangle.&lt;/p&gt;
&lt;p&gt;&lt;font size="4"&gt;Defining Visual States&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lh6.ggpht.com/-0gfGXuGcEgs/TyU4RXAb9KI/AAAAAAAAHHE/kyPzlpDFAaw/s1600-h/states2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="states" border="0" alt="states" align="right" src="http://lh5.ggpht.com/-RVLo6xVKmB4/TyU4SLEbcHI/AAAAAAAAHHI/GhTuoRGWaPI/states_thumb.png?imgmax=800" width="244" height="221"&gt;&lt;/a&gt;A CheckBox has certain states, the most obvious being Checked and Unchecked. Actually there are quite a lot more, and you can see them by clicking on the “States”&amp;nbsp; tab. Now all these states are &lt;em&gt;defined&lt;/em&gt;, but there are no &lt;em&gt;visuals&lt;/em&gt; connected to it anymore, since you have replaced the control template by something empty and started filling in yourself. This next step will bring a bit of those visual states back. To prepare for that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make sure the Rectangle is selected in the “Objects and Timeline”&amp;nbsp; panel left 
&lt;li&gt;In the Properties panel to the &lt;em&gt;right&lt;/em&gt; of the screen, scroll down to “Transform” 
&lt;li&gt;Expand the Transform panel if it’s collapsed 
&lt;li&gt;Selected the leftmost tab 
&lt;li&gt;Enter 0.5 in both X and Y boxes&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://lh6.ggpht.com/-m09RQUqmxTk/TyU4SlFmJ1I/AAAAAAAAHHQ/qKoCAIO3AUw/s1600-h/transform%25255B2%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin-top: -75px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="transform" border="0" alt="transform" align="right" src="http://lh5.ggpht.com/-6iTQ2Rmiz8M/TyU4S6CQ14I/AAAAAAAAHHc/FjlDd1LTeNU/transform_thumb.png?imgmax=800" width="244" height="92"&gt;&lt;/a&gt;XAML at this point:&lt;/p&gt;&lt;pre style="font-size: 11px"&gt;&amp;lt;Application.Resources&amp;gt;

  &amp;lt;ControlTemplate x:Key="Thumbupdowncheckboxtemplate" TargetType="CheckBox"&amp;gt;
    &amp;lt;Rectangle Fill="Green" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" 
	      d:DesignWidth="75" d:DesignHeight="75" RenderTransformOrigin="0.5,0.5"&amp;gt;
      &amp;lt;Rectangle.RenderTransform&amp;gt;
        &amp;lt;CompositeTransform TranslateX="0.5" TranslateY="0.5"/&amp;gt;
      &amp;lt;/Rectangle.RenderTransform&amp;gt;
      &amp;lt;Rectangle.OpacityMask&amp;gt;
        &amp;lt;ImageBrush Stretch="Fill" ImageSource="icons/thumbsup.png"/&amp;gt;
      &amp;lt;/Rectangle.OpacityMask&amp;gt;
    &amp;lt;/Rectangle&amp;gt;
  &amp;lt;/ControlTemplate&amp;gt;

  &amp;lt;Style x:Key="Thumbupdowncheckboxstyle" TargetType="CheckBox"&amp;gt;
    &amp;lt;Setter Property="Template" Value="{StaticResource Thumbupdowncheckboxtemplate}"/&amp;gt;
    &amp;lt;Setter Property="Width" Value="40"/&amp;gt;
    &amp;lt;Setter Property="Height" Value="40"/&amp;gt;
  &amp;lt;/Style&amp;gt;

&amp;lt;/Application.Resources&amp;gt;&lt;/pre&gt;
&lt;p&gt;In the “States”&amp;nbsp; panel, click on the “Checked” state. This will add quite some XAML code: you will see a “VisualStateManager.VisualStateGroups” tag appear, defining all three states of the “CheckStates”&amp;nbsp; group, i.e. “Checked”, “Unchecked”&amp;nbsp; and “Indeterminate”. &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Now Select the “Unchecked”&amp;nbsp; state 
&lt;li&gt;Make sure the “Rectangle” still is selected in the “Objects and Timeline”&amp;nbsp; panel 
&lt;li&gt;Select the “Properties” tab on the top right again 
&lt;li&gt;Select the (now green) “Fill” Rectangle again. 
&lt;li&gt;In the box where you previously typed “Green” (which will say ”#FF008000” now), type “Red”. The thumbs-up image will now turn red 
&lt;li&gt;&lt;a href="http://lh3.ggpht.com/-MzeDkV8fwPw/TyU4TqDDBrI/AAAAAAAAHHg/RBoIWO5FJH4/s1600-h/flip7.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="flip" border="0" alt="flip" align="right" src="http://lh6.ggpht.com/-UtVu4FcrIBM/TyU4UKPIyZI/AAAAAAAAHHs/IzEvIt1xT60/flip_thumb3.png?imgmax=800" width="244" height="85"&gt;&lt;/a&gt;Scroll down to “Transform” again 
&lt;li&gt;Select the &lt;em&gt;right&lt;/em&gt; most tab 
&lt;li&gt;Select the “Flip Y-axis” button, in the middle. The thumbs-up image will now flip vertically and turn into a thumbs-&lt;em&gt;down&lt;/em&gt; picture. 
&lt;li&gt;&lt;a href="http://lh5.ggpht.com/-2u9n96d_slY/TyU4VMWPu4I/AAAAAAAAHH0/b-Tf-wkOmdA/s1600-h/recording8.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="recording" border="0" alt="recording" align="right" src="http://lh6.ggpht.com/-yom1gCGVqxg/TyU4VyoZnSI/AAAAAAAAHH4/SpN-yQjl2Ps/recording_thumb4.png?imgmax=800" width="146" height="44"&gt;&lt;/a&gt;Locate the little red button on top of the design pane that says “Unchecked state recording is on”. Click it and the text should change into “Unchecked state recording is off”. &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;If you press F5, the project will compile and run (yes, that works from Blend as well), and you will see that the checkbox shows a green thumbs-up image when selected, and a red thumbs-down image when unselected.&lt;/p&gt;
&lt;p&gt;Now, for a finale to make things a little more visually appealing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://lh5.ggpht.com/-nofIQzmceEQ/TyU4WAsjfxI/AAAAAAAAHIA/fpzQY450IOU/s1600-h/Animate2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Animate" border="0" alt="Animate" align="right" src="http://lh4.ggpht.com/-tcjo-PTEnus/TyU4WqScNFI/AAAAAAAAHIM/853Ihnhu6ak/Animate_thumb.png?imgmax=800" width="244" height="74"&gt;&lt;/a&gt;Go back to the “States” tab again 
&lt;li&gt;Select the Textbox with “0 s” in the “Default transition” panel above state “Unchecked” 
&lt;li&gt;Type 0.5 in the text box 
&lt;li&gt;And press F5 again.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;You will now see the thumbs not simply flip: now it &lt;em&gt;rotates&lt;/em&gt; in half a second and change color from red via orange to green. By simply specifying a &lt;em&gt;time&lt;/em&gt; you tell the application to actually &lt;em&gt;infer&lt;/em&gt; an animation. And there you are. A completely customized, animated, thumb-up-thumbs-down control with just some clicking around. Code-wise it behaves just like a normal checkbox. And if you want to make more of these checkboxes, just select a standard CheckBox, right click it, Select “Edit template/Apply Resources/Thumbupdowncheckboxstyle” and boom – yet another Thumbup-thumbsdown control.&lt;/p&gt;
&lt;p&gt;Final XAML:&lt;/p&gt;&lt;pre style="font-size: 10px"&gt;&amp;lt;Application.Resources&amp;gt;

  &amp;lt;ControlTemplate x:Key="Thumbupdowncheckboxtemplate" TargetType="CheckBox"&amp;gt;
    &amp;lt;Rectangle x:Name="rectangle" Fill="Green" Width="{TemplateBinding Width}" 
               Height="{TemplateBinding Height}" 
               d:DesignWidth="75" d:DesignHeight="75" RenderTransformOrigin="0.5,0.5"&amp;gt;
      &amp;lt;Rectangle.RenderTransform&amp;gt;
        &amp;lt;CompositeTransform TranslateX="0.5" TranslateY="0.5"/&amp;gt;
      &amp;lt;/Rectangle.RenderTransform&amp;gt;
      &amp;lt;Rectangle.OpacityMask&amp;gt;
        &amp;lt;ImageBrush Stretch="Fill" ImageSource="icons/thumbsup.png"/&amp;gt;
      &amp;lt;/Rectangle.OpacityMask&amp;gt;
      &amp;lt;VisualStateManager.VisualStateGroups&amp;gt;
        &amp;lt;VisualStateGroup x:Name="CheckStates"&amp;gt;
          &amp;lt;VisualStateGroup.Transitions&amp;gt;
            &amp;lt;VisualTransition GeneratedDuration="0:0:0.5"/&amp;gt;
          &amp;lt;/VisualStateGroup.Transitions&amp;gt;
          &amp;lt;VisualState x:Name="Indeterminate"/&amp;gt;
          &amp;lt;VisualState x:Name="Unchecked"&amp;gt;
            &amp;lt;Storyboard&amp;gt;
              &amp;lt;DoubleAnimation Duration="0" To="-1" 
                    Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)" 
                    Storyboard.TargetName="rectangle" d:IsOptimized="True"/&amp;gt;
              &amp;lt;ColorAnimation Duration="0" To="Red" 
                   Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" 
                   Storyboard.TargetName="rectangle" d:IsOptimized="True"/&amp;gt;
            &amp;lt;/Storyboard&amp;gt;
          &amp;lt;/VisualState&amp;gt;
          &amp;lt;VisualState x:Name="Checked"/&amp;gt;
        &amp;lt;/VisualStateGroup&amp;gt;
      &amp;lt;/VisualStateManager.VisualStateGroups&amp;gt;
    &amp;lt;/Rectangle&amp;gt;
  &amp;lt;/ControlTemplate&amp;gt;

  &amp;lt;Style x:Key="Thumbupdowncheckboxstyle" TargetType="CheckBox"&amp;gt;
    &amp;lt;Setter Property="Template" Value="{StaticResource Thumbupdowncheckboxtemplate}"/&amp;gt;
    &amp;lt;Setter Property="Width" Value="40"/&amp;gt;
    &amp;lt;Setter Property="Height" Value="40"/&amp;gt;
  &amp;lt;/Style&amp;gt;
&lt;/application.resources&gt;
&lt;/pre&gt;
&lt;p&gt;You could of course go on and define all other states, but this already works pretty well IMHO ;-). Oh and by the way: this should work on any XAML platform, not just on Windows Phone. And for those who don’t like typing or copy-and-pasting, here is, as always, the complete &lt;a href="http://www.schaikweb.net/dotnetbyexample/ThumbsUpDown.zip" target="_blank"&gt;demo solution&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Thanks to &lt;a href="http://www.twitter.com/wmeints" target="_blank"&gt;Willem Meints&lt;/a&gt; for helping me out via twitter on default setters for styles.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5295746446529817470-8931341196290208521?l=dotnetbyexample.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/dotnetbyexample/~4/DJwMxfckeh0" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2012-01-29T17:36:37.324+01:00</atom:updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/-JA2sVHPDJh8/TyU4HE5aW0I/AAAAAAAAHE4/3103kPz5n24/s72-c/checkbox_thumb.png?imgmax=800" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://dotnetbyexample.blogspot.com/2012/01/templating-xaml-checkbox-to-thumbs.html</feedburner:origLink></item><item><title>JSON deserialization with JSON.net: basics</title><link>http://feedproxy.google.com/~r/blogspot/dotnetbyexample/~3/Kzoq_GKQmHw/json-deserialization-with-jsonnet.html</link><category>JSON</category><category>WP7NL</category><category>Windows Phone 7</category><category>wpdev</category><category>WP7</category><category>dotnetmag</category><author>noreply@blogger.com (Joost van Schaik)</author><pubDate>Sun, 22 Jan 2012 11:35:00 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5295746446529817470.post-6921523340631367310</guid><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/7FjFQOkjDKU-2rGvkEUJdmWeaKw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/7FjFQOkjDKU-2rGvkEUJdmWeaKw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/7FjFQOkjDKU-2rGvkEUJdmWeaKw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/7FjFQOkjDKU-2rGvkEUJdmWeaKw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;I’ve been contemplating an article about handling JSON for some time now, but it turned out to be a rather long article and writing &lt;a href="http://www.bing.com/search?q=steven+sinofsky+%22long+blog+post%22&amp;amp;go=&amp;amp;form=QBLH&amp;amp;filt=all" target="_blank"&gt;extremely large blog posts is someone else’s trade mark these days&lt;/a&gt; ;-). So I’d thought to try something new, and write a short series in three parts. &lt;/p&gt; &lt;ul&gt; &lt;li&gt;Part 1 handles the basics  &lt;li&gt;Part 2 handles advanced deserialization with class hierarchies  &lt;li&gt;Part 3 handles a caching-and-updating scenarios.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;And this is part 1 ;-)&lt;/p&gt; &lt;p&gt;This whole article actually boils down to &lt;em&gt;one line of code&lt;/em&gt;, but I need to go trough some hooplah to show you how to use it. It all begins with the data. Consider this piece of quite readable JSON, describing a few recent &lt;a href="http://www.microsoft.com/windowsphone/" target="_blank"&gt;Windows Phone&lt;/a&gt; models. &lt;/p&gt;&lt;pre&gt;[
  {
    "Brand": "Nokia","Type" : "Lumia 800",
    "Specs":{"Storage" : "16GB", "Memory": "512MB","Screensize" : "3.7"}
  },
  {
    "Brand": "Nokia", "Type" : "Lumia 710",
    "Specs":{"Storage" : "8GB","Memory": "512MB","Screensize" : "3.7"}
  },  
  { "Brand": "Nokia","Type" : "Lumia 900",
    "Specs":{"Storage" : "8GB", "Memory": "512MB","Screensize" : "4.3" }
  },
  { "Brand": "HTC ","Type" : "Titan II",
    "Specs":{"Storage" : "16GB", "Memory": "512MB","Screensize" : "4.7" }
  },
  { "Brand": "HTC ","Type" : "Radar",
    "Specs":{"Storage" : "8GB", "Memory": "512MB","Screensize" : "3.8" }
  }
]&lt;/pre&gt;
&lt;p&gt;JSON is rather compact, which is a great feature when you are developing for mobile devices. It has also a few downsides as far as client programming is concerned: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;generating client code for it that does all the parsing and calling, as for SOAP, is not a standard feature of Visual Studio, 
&lt;li&gt;it’s almost impossible to read for an ordinary human being, 
&lt;li&gt;deciphering it into classes is a lot of work, 
&lt;li&gt;hand coding a parser for it is not fun. &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Which is why you don’t. There are several ways of generating classes from JSON, the simplest way is this website: &lt;a href="http://json2csharp.com/" target="_blank"&gt;json2csharp by Jonathan Keith&lt;/a&gt;. You copy a JSON result into the upper textbox, hit the “Generate” button and out come your classes:&lt;a href="http://lh4.ggpht.com/-xMRvNkMvoHw/TxxlACmjF8I/AAAAAAAAHEI/dwzKe78iBdY/s1600-h/Json2Csharp%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Json2Csharp" border="0" alt="Json2Csharp" src="http://lh6.ggpht.com/-B614r5ue5rM/TxxlBC2NHHI/AAAAAAAAHEQ/Hwahqj_hsYM/Json2Csharp_thumb%25255B1%25255D.png?imgmax=800" width="617" height="591"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There are more sites that do the same, by the way, but this is what I use. Next steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fire up Visual Studio 
&lt;li&gt;Create a new Windows Phone project (for instance JsonDemo) 
&lt;li&gt;Plonk the classes generated above in the project. Bonus cookies if you split them in separate files and add namespaces to them. Bonus donut if you, like me, think “RootObject” is actually a pretty ugly name for an object - &lt;b&gt;so change it to "&lt;i&gt;Phone&lt;/i&gt;"&lt;/b&gt;. 
&lt;li&gt;Click Tools/Library Package Manager/Manage NuGet Packages for Solution (you &lt;em&gt;do&lt;/em&gt; have the NuGet Package Manager installed, don’t you? If not, stop whatever you are doing now and get it &lt;em&gt;&lt;a href="http://visualstudiogallery.msdn.microsoft.com/27077b70-9dad-4c64-adcf-c7cf6bc9970c" target="_blank"&gt;right this instance&lt;/a&gt;&lt;/em&gt;, you hear me ;)? ) 
&lt;li&gt;Search for JSON.Net 
&lt;li&gt;Click install. This will add a reference to NewtonSoft.Json.dll to your product. 
&lt;li&gt;Add references to Microsoft.Phone.Reactive and System.Observable because they are going to be needed in the next step.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;To make the result visible, add some XAML to the default content panel in Mainpage.Xaml – just a button and a templated ListBox, no rocket science here:&lt;/p&gt;&lt;pre&gt;&amp;lt;StackPanel&amp;gt;
  &amp;lt;Button Name="Load"
      VerticalAlignment="Top"
      Content="Load phones" Click="Load_Click" /&amp;gt;
  &amp;lt;ListBox x:Name="PhoneList" Height="532"&amp;gt;
    &amp;lt;ListBox.ItemTemplate&amp;gt;
      &amp;lt;DataTemplate&amp;gt;
        &amp;lt;StackPanel Orientation="Horizontal"&amp;gt;
          &amp;lt;TextBlock Text="{Binding Brand}" 
                 Margin="0,0,12,0" /&amp;gt;
          &amp;lt;TextBlock Text="{Binding Type}"/&amp;gt;
        &amp;lt;/StackPanel&amp;gt;
      &amp;lt;/DataTemplate&amp;gt;
    &amp;lt;/ListBox.ItemTemplate&amp;gt;
  &amp;lt;/ListBox&amp;gt;
&amp;lt;/StackPanel&amp;gt;&lt;/pre&gt;
&lt;p&gt;Finally, open MainPage.Xaml.cs and add the method Load_Click as displayed below. &lt;/p&gt;&lt;pre&gt;using System;
using System.Collections.Generic;
using System.Net;
using System.Windows;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Reactive;
using Newtonsoft.Json;

namespace JsonDemo
{
  public partial class MainPage : PhoneApplicationPage
  {
    // Constructor
    public MainPage()
    {
      InitializeComponent();
    }

    private void Load_Click(object sender, RoutedEventArgs e)
    {
      var w = new WebClient();
      Observable
        .FromEvent&amp;lt;DownloadStringCompletedEventArgs&amp;gt;(w, "DownloadStringCompleted")
        .Subscribe(r =&amp;gt;
        {
          &lt;font color="#ff0000"&gt;&lt;strong&gt;var deserialized = 
            JsonConvert.DeserializeObject&amp;lt;List&amp;lt;Phone&amp;gt;&amp;gt;(r.EventArgs.Result);&lt;/strong&gt;&lt;/font&gt;
          PhoneList.ItemsSource = deserialized;
        });
      w.DownloadStringAsync(
        new Uri("http://www.schaikweb.net/dotnetbyexample/JSONPhones1.txt"));
    }
  }
}

&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://lh4.ggpht.com/-YWUjM24StU4/TxxlBkdV2CI/AAAAAAAAHEU/7SJI7Bg1T3Q/s1600-h/JsonSerializer%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="JsonSerializer" border="0" alt="JsonSerializer" align="right" src="http://lh6.ggpht.com/-_WHR6AzqZLM/TxxlCC1xDqI/AAAAAAAAHEg/2PXWjQSpbPM/JsonSerializer_thumb%25255B1%25255D.png?imgmax=800" width="141" height="265"&gt;&lt;/a&gt;And there it is, the one line of code that this is all about. Call the DeserializeObject method, template it with the return type you want, and stuff the JSON string in it. Result: a list of objects with their properties filled, even if there are things like nested objects (specs in these case) and arrays in there.&lt;/p&gt;
&lt;p&gt;If you run &lt;a href="http://www.schaikweb.net/dotnetbyexample/JSONDemo1.zip" target="_blank"&gt;the demo solution&lt;/a&gt; you get the result displayed in the image on the right. Keep in mind this code is by no means Windows Phone specific. There are JSON.Net implementations for virtually all frameworks available. So should you feel the need to use this from Silverlight or full .NET: it’s there.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Finally, a ninja tip:&lt;/strong&gt; &lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Click Tools/Library Package Manager/Manage NuGet Packages for Solution&amp;nbsp; again&lt;/li&gt;
&lt;li&gt;Search for &lt;a href="http://nuget.org/packages/SharpGIS.GZipWebClient" target="_blank"&gt;SharpGIS.GZipWebClient&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Click install&lt;/li&gt;
&lt;li&gt;Change “WebClient” in the Load_Click method to &lt;strong&gt;SharpGIS.GZipWebClient&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;This plug-in replacement for WebClient by &lt;a href="http://twitter.com/dotmorten" target="_blank"&gt;Morten Nielsen&lt;/a&gt; adds support for GZIP compressed web requests – this reduces network traffic even further, apparently boosting load performance significantly. You won’t really notice the difference on such a small data files as used in this sample, but as your JSON return values get larger, so will be the impact of using this library.&lt;/p&gt;
&lt;p&gt;For the record: I am not ill nor do I have forsaken MVVM, but I tried to make the example as simple as possible so yes, I used a little code behind, as to not to cloud the solution in architectural frills. ;-)&lt;/p&gt;
&lt;p&gt;Thanks to &lt;a href="http://blogs.microsoft.nl/blogs/mhoekstra/default.aspx" target="_blank"&gt;Matthijs Hoekstra&lt;/a&gt; for putting me on track to this, and to fellow #wp7nl developer &lt;a href="https://twitter.com/#!/leonzandman" target="_blank"&gt;Leon Zandman&lt;/a&gt; for correcting some annoying typos.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5295746446529817470-6921523340631367310?l=dotnetbyexample.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/dotnetbyexample/~4/Kzoq_GKQmHw" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2012-01-24T15:05:13.836+01:00</atom:updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/-B614r5ue5rM/TxxlBC2NHHI/AAAAAAAAHEQ/Hwahqj_hsYM/s72-c/Json2Csharp_thumb%25255B1%25255D.png?imgmax=800" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://dotnetbyexample.blogspot.com/2012/01/json-deserialization-with-jsonnet.html</feedburner:origLink></item><item><title>A Windows Phone 7 behavior to show an image background for a search string</title><link>http://feedproxy.google.com/~r/blogspot/dotnetbyexample/~3/1hHz-Eds0B4/windows-phone-7-behavior-to-show-image.html</link><category>Rx</category><category>behavior</category><category>WP7NL</category><category>wpdev</category><category>WP7</category><category>Bing Search API</category><category>Reactive</category><category>dotnetmag</category><author>noreply@blogger.com (Joost van Schaik)</author><pubDate>Sat, 31 Dec 2011 08:59:00 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5295746446529817470.post-7267797457410060429</guid><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/vdbF_JpnCtO4aIjm1N7k3B28euo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vdbF_JpnCtO4aIjm1N7k3B28euo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/vdbF_JpnCtO4aIjm1N7k3B28euo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vdbF_JpnCtO4aIjm1N7k3B28euo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;On New Year’s Eve I can’t help but writing this last bit of 2011: yesterday on a &lt;a href="http://twitter.com/#!/search/%23wp7nl" target="_blank"&gt;#wp7nl&lt;/a&gt; developer’s meet up, which was basically a free-for-all fun hacking event organized by &lt;a href="http://blogs.microsoft.nl/blogs/mhoekstra/default.aspx" target="_blank"&gt;Matthijs Hoekstra&lt;/a&gt;, I wrote a little thingy for &lt;a href="http://www.microsoft.com/windowsphone/" target="_blank"&gt;Windows Phone 7&lt;/a&gt; that accepts a string, tries to find an image for it using Bing Image search and displays it as a background. Of course it’s a behavior – I write behaviors a dozen, because the concept of reusable dynamic behavior is something that fits very well with the way I think. Call me the behaviornator if you like ;-)&lt;/p&gt; &lt;p&gt;It’s very simple, it’s quite fun, demonstrates a little Rx usage, makes quite unusual use of the Bing Image Search api - and it will play a supporting act in my newest Windows Phone 7 app. The basic structure of the behavior is set up utilizing the #wp7nl library &lt;a href="http://dotnetbyexample.blogspot.com/2011/11/safe-event-detachment-base-class-for.html" target="_blank"&gt;SafeBehavior&lt;/a&gt; that I described earlier: &lt;/p&gt;&lt;pre style="font-size: 12px"&gt;using System;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Xml;
using System.Xml.Linq;
using Microsoft.Phone.Reactive;
 
namespace Wp7nl.Behaviors
{
  /// &amp;lt;summary&amp;gt;
  /// A behavior that puts an image on the background of the Attched object
  /// using Bing Image Search
  /// &amp;lt;/summary&amp;gt;
  public class DynamicBackgroundBehavior : SafeBehavior&amp;lt;Panel&amp;gt;
  {
    private ImageBrush backgroundBrush;
    
    public DynamicBackgroundBehavior()
    {
      Opacity = 1.0;
    }

    #region SearchString
    public const string SearchStringPropertyName = "SearchString";

    /// &amp;lt;summary&amp;gt;
    /// The search string to be used on Bing Maps
    /// &amp;lt;/summary&amp;gt;
    public string SearchString
    {
      get { return (string)GetValue(SearchStringProperty); }
      set { SetValue(SearchStringProperty, value); }
    }

    public static readonly DependencyProperty SearchStringProperty = 
        DependencyProperty.Register(
        SearchStringPropertyName,
        typeof(string),
        typeof(DynamicBackgroundBehavior),
        new PropertyMetadata(String.Empty, SearchStringChanged));

    public static void SearchStringChanged(DependencyObject d, 
                                           DependencyPropertyChangedEventArgs e)
    {
      var behavior = d as DynamicBackgroundBehavior;
      if (behavior != null)
      {
        behavior.StartGetFirstImage((string)e.NewValue);
      }
    }
    #endregion

    /// &amp;lt;summary&amp;gt;
    /// Bing search key
    /// &amp;lt;/summary&amp;gt;
    public string BingSearchKey { get; set; }

    /// &amp;lt;summary&amp;gt;
    /// Stretch used for the image
    /// &amp;lt;/summary&amp;gt;
    public Stretch Stretch { get; set; }

    /// &amp;lt;summary&amp;gt;
    /// Opacity used for the image
    /// &amp;lt;/summary&amp;gt;
    public double Opacity { get; set; }
  }
}&lt;/pre&gt;
&lt;p&gt;In short, this behavior has four properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Opacity 
&lt;li&gt;Stretch 
&lt;li&gt;BingSearchKey 
&lt;li&gt;SearchString&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://lh3.ggpht.com/-AQ4UVdGYxDc/Tv8_V_tECBI/AAAAAAAAHDk/3hL55-6AUnU/s1600-h/BingSearchApi%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="BingSearchApi" border="0" alt="BingSearchApi" align="right" src="http://lh4.ggpht.com/-u7Taj7tJk4M/Tv8_WeCTgSI/AAAAAAAAHDo/3i43biKarFY/BingSearchApi_thumb%25255B1%25255D.png?imgmax=800" width="254" height="256"&gt;&lt;/a&gt;Opacity and Stretch are just simple properties for the images that is going to be displayed. SearchString is the string that’s going to be used to find an image for. This is a dependency property – so it can be used in data binding. Note the SearchStringChanged method – this is called when the SearchString property changes. That in turn is firing the method StartGetFirstImage, that will start the actual search.&lt;/p&gt;
&lt;p&gt;BingSearchKey is a 40-character long string identifying your application. You have to create a key for your application on &lt;a href="http://www.bing.com/toolbox/bingdeveloper/" target="_blank"&gt;the Bing Developer portal&lt;/a&gt;. Click the left button (“Sign in – Bing Search API”) and fill in the form depicted to the right(click for larger image).&lt;/p&gt;
&lt;p&gt;Note: the behavior references Microsoft.Phone.Reactive – so the project holding this should Microsoft.Phone.Reactive.dll and System.Observable.dll&lt;/p&gt;
&lt;p&gt;Moving on to the setup of the behavior, which is very simple now since we are building upon the SafeBehavior:&lt;/p&gt;&lt;pre style="font-size: 12px"&gt;/// &amp;lt;summary&amp;gt;
/// Setup the behavior
/// &amp;lt;/summary&amp;gt;
protected override void OnSetup()
{
  backgroundBrush = new ImageBrush
  {
    Stretch = Stretch,
    Opacity = Opacity
  };

  // Set the image brush to the background of the Panel 
  AssociatedObject.Background = backgroundBrush;
}&lt;/pre&gt;
&lt;p&gt;Simply put: create an Image brush using the property settings, and put it as background on the GUI element to which the behavior is attached.&lt;/p&gt;
&lt;p&gt;The method that’s called from SearchStringChanged (which is fired as the SearchString dependency property changes) is implemented as showed below:&lt;/p&gt;&lt;pre style="font-size: 12px"&gt;/// &amp;lt;summary&amp;gt;
/// Start the image request using Bing Serach
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="searchString"&amp;gt;&amp;lt;/param&amp;gt;
protected void StartGetFirstImage(string searchString)
{
  var queryUri = 
    string.Format(
      "http://api.bing.net/xml.aspx?Appid={0}&amp;amp;query={1}&amp;amp;sources=image",
      BingSearchKey, searchString);
  var request = WebRequest.Create(queryUri) as HttpWebRequest;
  var response = 
    Observable.FromAsyncPattern&amp;lt;WebResponse&amp;gt;(
      request.BeginGetResponse, request.EndGetResponse)();
  response.Subscribe(WebClientOpenReadCompleted, WebClientOpenReadError);
}&lt;/pre&gt;
&lt;p&gt;An Uri is formed using the BingSearchKey and the actual search string – and the clause “sources=image”, telling Bing to return images. That Uri is fed to a standard WebRequest. And then the Rx framework comes into play to easily process the async read process. The Observable.FromAsyncPattern and Subscribe usage has the distinct advantage of not having to attach all kind of event handlers, trap errors with try-catch blocks, and not forgetting to detach the event handlers when the reading is done. The Rx framework handles this all, so I don’t have to worry about that.&lt;/p&gt;
&lt;p&gt;The final piece of the behavior – the actual processing of the image:&lt;/p&gt;&lt;pre style="font-size: 12px"&gt;/// &amp;lt;summary&amp;gt;
/// Called when image search returns
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="result"&amp;gt;&amp;lt;/param&amp;gt;
private void WebClientOpenReadCompleted(WebResponse result)
{
  using (var stream = result.GetResponseStream())
  {
    using (var reader = XmlReader.Create(stream,
       new XmlReaderSettings { DtdProcessing = DtdProcessing.Ignore }))
    {
      var doc = XDocument.Load(reader);

      // Get the first image from the result
      XNamespace ns = "http://schemas.microsoft.com/LiveSearch/2008/04/XML/multimedia";
      if (doc.Root != null)
      {
        var firstImage = doc.Root.Descendants(ns + "MediaUrl").FirstOrDefault();
        if (firstImage != null)
        {
          Deployment.Current.Dispatcher.BeginInvoke(() =&amp;gt;
            {
              var bi = new BitmapImage
                {
                  UriSource = new Uri(firstImage.Value),
                  CreateOptions = BitmapCreateOptions.BackgroundCreation
                };
              backgroundBrush.ImageSource = bi;
            });
        }
      }
    }
  }
}

/// &amp;lt;summary&amp;gt;
/// Called upon a search error (not used)
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="ex"&amp;gt;&amp;lt;/param&amp;gt;
private void WebClientOpenReadError(Exception ex)
{
}&lt;/pre&gt;
&lt;p&gt;Since the xml.aspx page is referenced, Bing returns the result as a xml document. If you are interested in the details of the Bing Search result, feel free to explore the xml document – this code basically just finds the first “MediaUrl” tag, makes a BitMapImage from it, and puts the result into the backgroundBrush. And we’re done.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lh4.ggpht.com/-aWjRXVtW-M4/Tv8_XnamfOI/AAAAAAAAHD0/LH_iVck6juw/s1600-h/carrotdemo%25255B2%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 8px 0px 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top: 0px; border-right: 0px; padding-top: 0px" title="carrotdemo" border="0" alt="carrotdemo" align="left" src="http://lh5.ggpht.com/-eDGPUq0fuI8/Tv8_YFK5nAI/AAAAAAAAHD4/BiRqCbwSpEo/carrotdemo_thumb.png?imgmax=800" width="133" height="244"&gt;&lt;/a&gt;Put this behavior on a descendant of Panel (a Grid, for instance), fill  the BingSearchKey property with a valid key, databind the “SearchString” property to a string in a ViewModel and as soon as the value of SearchString changes, the behavior will show the first available image returned by Bing Image search as a background on that grid. &lt;/p&gt;
&lt;p&gt;I’ve put together &lt;a href="http://www.schaikweb.net/dotnetbyexampe/DynaBackgroundDemo.zip" target="_blank"&gt;a small demo application containing and demonstrating the behavior&lt;/a&gt;. It deviates in two ways from my usual mode of operation. First, does not run out of the box – you will have to get your own Bing Search API key first. Second: it does &lt;em&gt;not&lt;/em&gt; use MVVM – I’ve data bound the behavior’s SearchString property directly to a TextBox’s Text property, which makes the behavior start to search for background immediately as you start typing, as showed to the left. So if you type “carrot” in the textbox you get, well – an image showing carrots ;-)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Well, that’s all for 2011. A very special year from me with some ups and downs, with getting a Windows Phone Development MVP award definitely being the top event in the "ups" category. Now onwards to 2012, which I think will prove to be a very exciting year indeed. I hope you all will continue to enjoy this blog as I did - and you apparently did in 2011 as well.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5295746446529817470-7267797457410060429?l=dotnetbyexample.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/dotnetbyexample/~4/1hHz-Eds0B4" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2012-01-04T08:36:08.251+01:00</atom:updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/-u7Taj7tJk4M/Tv8_WeCTgSI/AAAAAAAAHDo/3i43biKarFY/s72-c/BingSearchApi_thumb%25255B1%25255D.png?imgmax=800" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://dotnetbyexample.blogspot.com/2011/12/windows-phone-7-behavior-to-show-image.html</feedburner:origLink></item><item><title>Re-imagining the behavior to show the Windows Phone 7 camera as background</title><link>http://feedproxy.google.com/~r/blogspot/dotnetbyexample/~3/sNRBlTKM7ms/rethinking-behavior-to-show-windows.html</link><category>behavior</category><category>WP7NL</category><category>Windows Phone 7</category><category>wpdev</category><category>WP7</category><category>dotnetmag</category><author>noreply@blogger.com (Joost van Schaik)</author><pubDate>Sat, 03 Dec 2011 04:44:00 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5295746446529817470.post-7382731371873658108</guid><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/d1xnH5uSCSsNI2gpV0_a_ajNCg8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/d1xnH5uSCSsNI2gpV0_a_ajNCg8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/d1xnH5uSCSsNI2gpV0_a_ajNCg8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/d1xnH5uSCSsNI2gpV0_a_ajNCg8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;This blog turns out not only to be a collection of how-to samples but also a record of my evolution as a &lt;a href="http://www.microsoft.com/windowsphone/" target="_blank"&gt;Windows Phone 7&lt;/a&gt; developer. At the end of my previous post, &lt;a href="http://dotnetbyexample.blogspot.com/2011/11/safe-event-detachment-base-class-for.html"&gt;Safe event detachment base class for Windows Phone 7 behaviors&lt;/a&gt;, I promised a usage example and I decided to re-implement the &lt;a href="http://dotnetbyexample.blogspot.com/2011/10/behavior-to-show-windows-phone-7-camera.html"&gt;behavior to show the Windows Phone 7 camera as background&lt;/a&gt; using the SafeBehavior as a base class. This makes the code considerable easier.&lt;/p&gt; &lt;p&gt;The base setup of the re-implemented behavior is pretty simple:&lt;/p&gt;&lt;pre style="font-size: 12px"&gt;using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Navigation;
using Microsoft.Devices;
using Microsoft.Phone.Controls;

namespace Wp7nl.Behaviors
{
  /// &amp;lt;summary&amp;gt;
  /// A behavior that shows a camera view on the background of a panel
  /// &amp;lt;/summary&amp;gt;
  public class CameraViewBackgroundBehavior : SafeBehavior&amp;lt;Panel&amp;gt;
  {

    private PhotoCamera camera;
    private VideoBrush backgroundBrush;

    public CameraViewBackgroundBehavior()
    {
      ListenToPageBackEvent = true;
    }
  }
}&lt;/pre&gt;
&lt;p&gt;Note this behavior needs to detect the user navigating back to the page – this in necessary because we need to do something with the camera.&lt;/p&gt;
&lt;p&gt;In stead of all the song and dance for attaching and detaching events using the &lt;a href="http://www.schaikweb.net/dotnetbyexample/beh.zip" target="_blank"&gt;snippet&lt;/a&gt; I published earlier, it’s now a matter of overriding the OnSetup and OnCleanup methods to initialize the camera:&lt;/p&gt;&lt;pre style="font-size: 12px"&gt;protected override void OnSetup()
{
  if (camera == null)
  {
    camera = new PhotoCamera();
    ParentPage.OrientationChanged += ParentPageOrientationChanged;
  }

  // Create a video brush with the right parameters
  backgroundBrush = new VideoBrush
                      {
                        Stretch = Stretch.UniformToFill,
                        AlignmentX = AlignmentX.Left,
                        AlignmentY = AlignmentY.Top
                      };

  // Set the video brush to the background of the panel 
  // and and do an initial display
  AssociatedObject.Background = backgroundBrush;
  backgroundBrush.SetSource(camera);
  SetVideoOrientation(ParentPage.Orientation);
}

protected override void OnCleanup()
{
  ParentPage.OrientationChanged -= ParentPageOrientationChanged;
  camera.Dispose();
  camera = null;
}&lt;/pre&gt;
&lt;p&gt;This behavior also needs to do some action when the user actually navigates back to the page, which you can do by override the OnParentPageNavigated method - in this case, re-initializing the whole behavior&lt;/p&gt;&lt;pre style="font-size: 12px"&gt;/// &amp;lt;summary&amp;gt;
/// Fired whe page navigation happens
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="sender"&amp;gt;&amp;lt;/param&amp;gt;
/// &amp;lt;param name="e"&amp;gt;&amp;lt;/param&amp;gt;
protected override void OnParentPageNavigated(object sender, NavigationEventArgs e)
{
  // Re-setup when this page is navigated BACK to
 if( IsNavigatingBackToBehaviorPage(e))
 {
   if (camera != null)
   {
     OnCleanup();
     OnSetup();
   }
  }
}&lt;/pre&gt;
&lt;p&gt;The actual implementation of showing the camera background has hardly changed, and is only mentioned here for the sake of completeness:&lt;/p&gt;&lt;pre style="font-size: 12px"&gt;private void ParentPageOrientationChanged(object sender, OrientationChangedEventArgs e)
{
  SetVideoOrientation(e.Orientation);
}

/// &amp;lt;summary&amp;gt;
/// Sets background video brush parameters based upon page orientation
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="orientation"&amp;gt;&amp;lt;/param&amp;gt;
private void SetVideoOrientation(PageOrientation orientation)
{
  System.Diagnostics.Debug.WriteLine("Switching to {0}", orientation);
  switch (orientation)
  {
    case PageOrientation.PortraitUp:
      backgroundBrush.Transform = 
        new CompositeTransform { Rotation = 90, TranslateX = 480 };
      break;
    case PageOrientation.LandscapeLeft:
      backgroundBrush.Transform = null;
      break;
    case PageOrientation.LandscapeRight:
      if (Microsoft.Phone.Shell.SystemTray.IsVisible )
      {
        backgroundBrush.Transform = 
          new CompositeTransform { Rotation = 180, TranslateX = 728, TranslateY = 480 };
      }
      else
      {
        backgroundBrush.Transform = 
            new CompositeTransform { Rotation = 180, TranslateX = 800, TranslateY = 480 };
      }
      break;
  }
}&lt;/PRE&lt;&lt;p&gt;&lt;/pre&gt;
&lt;p&gt;As this post demonstrated, using the SafeBehavior as a base class makes life a lot easier than implementing the whole pattern over and over again, even when using a snippet. &lt;/p&gt;
&lt;p&gt;Code is part of the the #&lt;a href="http://wp7nl.codeplex.com/" target="_blank"&gt;wp7nl library on codeplex&lt;/a&gt; and can be found &lt;a href="http://wp7nl.codeplex.com/SourceControl/changeset/view/11210#214133" target="_blank"&gt;here&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5295746446529817470-7382731371873658108?l=dotnetbyexample.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/dotnetbyexample/~4/sNRBlTKM7ms" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2011-12-03T13:45:39.858+01:00</atom:updated><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://dotnetbyexample.blogspot.com/2011/12/rethinking-behavior-to-show-windows.html</feedburner:origLink></item><item><title>Safe event detachment base class for Windows Phone 7 behaviors</title><link>http://feedproxy.google.com/~r/blogspot/dotnetbyexample/~3/d60ZksYrZHg/safe-event-detachment-base-class-for.html</link><category>behavior</category><category>WP7NL</category><category>Windows Phone 7</category><category>wpdev</category><category>WP7</category><category>dotnetmag</category><author>noreply@blogger.com (Joost van Schaik)</author><pubDate>Sat, 26 Nov 2011 10:16:00 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5295746446529817470.post-1967210838325718409</guid><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/5LCBPxDu5cfBoS57AM7mTPH_nN8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5LCBPxDu5cfBoS57AM7mTPH_nN8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/5LCBPxDu5cfBoS57AM7mTPH_nN8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5LCBPxDu5cfBoS57AM7mTPH_nN8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Some time ago I blogged about the &lt;a href="http://dotnetbyexample.blogspot.com/2011/04/safe-event-detachment-pattern-for.html" target="_blank"&gt;Safe Event Detachment ‘pattern’ for behaviors&lt;/a&gt; and even included a snippet that made implementing this pattern easier. When I started to use this pattern more often myself I observed quite some code duplication appearing and I don’t like that. What’s more – although the pattern works well under Silverlight and WPF, there are some unique situations in &lt;a href="http://www.microsoft.com/windowsphone/" target="_blank"&gt;Windows Phone 7&lt;/a&gt; that need some extra attention – particularly the situation in which the user is navigating &lt;em&gt;back&lt;/em&gt; to a page containing such a behavior. For when the user is navigation &lt;em&gt;from&lt;/em&gt; the page, the AssociatedObject’s &lt;em&gt;Unloaded&lt;/em&gt; event fires and the behavior is de-activated. If the user then moves back to the page – the AssociatedObject’s &lt;em&gt;OnAttached&lt;/em&gt; event is &lt;em&gt;not&lt;/em&gt; fired and the behavior is not re-initialized. &lt;/p&gt;So I set out to create a base class taking care of most of this initalization hooplah without bothering the developer too much. This turned out to be not so simple as I thought. But anyway – thinks worked out. The initial setup of the base class is like this:&lt;pre style="font-size: 12px"&gt;using System;
using System.Windows;
using System.Windows.Interactivity;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;

namespace Wp7nl.Behaviors
{
  /// &amp;lt;summary&amp;gt;
  /// A base class implementing the safe event detachment pattern for behaviors.
  /// Optional re-init after page back navigation.
  /// &amp;lt;/summary&amp;gt;
  /// &amp;lt;typeparam name="T"&amp;gt;The framework element type this behavior attaches to&amp;lt;/typeparam&amp;gt;
  public abstract class SafeBehavior&amp;lt;T&amp;gt; : Behavior&amp;lt;T&amp;gt; where T : FrameworkElement
  {
    protected SafeBehavior()
    {
      IsCleanedUp = true;
    }

    /// &amp;lt;summary&amp;gt;
    ///Setting this value to true in the constructor makes the behavior
    ///re-init after a page back event.
    /// &amp;lt;/summary&amp;gt;
    protected bool ListenToPageBackEvent { get; set; }

    /// &amp;lt;summary&amp;gt;
    /// The page this behavior is on
    /// &amp;lt;/summary&amp;gt;
    protected PhoneApplicationFrame ParentPage;

    /// &amp;lt;summary&amp;gt;
    /// The uri of the page this behavior is on
    /// &amp;lt;/summary&amp;gt;
    private Uri pageSource;

    protected override void OnAttached()
    {
      base.OnAttached();
      InitBehavior();
    }

    /// &amp;lt;summary&amp;gt;
    /// Does the initial wiring of events
    /// &amp;lt;/summary&amp;gt;
    protected void InitBehavior()
    {
      if (IsCleanedUp)
      {
        IsCleanedUp = false;
        AssociatedObject.Loaded += AssociatedObjectLoaded;
        AssociatedObject.Unloaded += AssociatedObjectUnloaded;
      }
    }
  }
}&lt;/pre&gt;
&lt;p&gt;The comments already give away which direction this is going to take: the behavior keeps track of the page it’s on &lt;em&gt;and that page’s u&lt;/em&gt;&lt;em&gt;ri&lt;/em&gt; to track if the user is navigating back to this page. If you don’t want this behavior, do nothing. If you &lt;em&gt;need&lt;/em&gt; to track the user navigating back to the page (and believe me, in Windows Phone 7 you want that in most of the cases), set ListenToPageBackEvent to true in the behavior’s constructor. The setting up of this tracking is done in the next method:&lt;/p&gt;&lt;pre style="font-size: 12px"&gt;/// &amp;lt;summary&amp;gt;
/// Does further event wiring and initialization after load
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="sender"&amp;gt;&amp;lt;/param&amp;gt;
/// &amp;lt;param name="e"&amp;gt;&amp;lt;/param&amp;gt;
private void AssociatedObjectLoaded(object sender, RoutedEventArgs e)
{
  // Find the page this control is on and listen to its orientation changed events
  if (ParentPage == null &amp;amp;&amp;amp; ListenToPageBackEvent)
  {
    ParentPage = Application.Current.RootVisual as PhoneApplicationFrame;
    pageSource = ParentPage.CurrentSource;
    ParentPage.Navigated += ParentPageNavigated;
  }
  OnSetup();
}

/// &amp;lt;summary&amp;gt;
/// Fired whe page navigation happens
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="sender"&amp;gt;&amp;lt;/param&amp;gt;
/// &amp;lt;param name="e"&amp;gt;&amp;lt;/param&amp;gt;
private void ParentPageNavigated(object sender, NavigationEventArgs e)
{
  // Re-setup when this page is navigated BACK to
  if (IsNavigatingBackToBehaviorPage(e))
  {
    if (IsCleanedUp)
    {
      InitBehavior();
    }
  }
  OnParentPageNavigated(sender, e);
}

/// &amp;lt;summary&amp;gt;
/// Checks if the back navigation navigates back to the page
/// on which this behavior is on
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="e"&amp;gt;&amp;lt;/param&amp;gt;
/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
protected bool IsNavigatingBackToBehaviorPage(NavigationEventArgs e)
{
  return (e.NavigationMode == NavigationMode.Back &amp;amp;&amp;amp; e.Uri.Equals(pageSource));
}
&lt;/pre&gt;
&lt;p&gt;Now if you have set ListenToPageBackEvent to true, it keeps the root visual (i.e. the page on which the behavior is plonked) in ParentPage, it’s uri in pageSouce &lt;em&gt;and attaches&lt;/em&gt; an listener to the ParentPageNavigated event of this page. Now if a navigation event happens, the IsNavigatingBackToBehaviorPage checks by comparing uri’s if the user is actually navigating &lt;em&gt;back&lt;/em&gt; to this page.&lt;/p&gt;
&lt;p&gt;All very interesting, but the most important is: there are two methods OnSetup and OnParentPageNavigated in this class which are called. They are basically emtpy and form your hook points into this:&lt;/p&gt;&lt;pre style="font-size: 12px"&gt;/// &amp;lt;summary&amp;gt;
/// Override this to add your re-init
/// &amp;lt;/summary&amp;gt;    
protected virtual void OnParentPageNavigated(object sender, NavigationEventArgs e)
{     
}

/// &amp;lt;summary&amp;gt;
/// Override this to add your own setup
/// &amp;lt;/summary&amp;gt;
protected virtual void OnSetup()
{
}
&lt;/pre&gt;
&lt;p&gt;So far for the setup stuff: the cleanup stuff is a lot simpler:&lt;/p&gt;&lt;pre style="font-size: 12px"&gt;protected bool IsCleanedUp { get; private set; }

/// &amp;lt;summary&amp;gt;
/// Executes at OnDetaching or OnUnloaded (usually the last)
/// &amp;lt;/summary&amp;gt;
private void Cleanup()
{
  if (!IsCleanedUp)
  {
    AssociatedObject.Loaded -= AssociatedObjectLoaded;
    AssociatedObject.Unloaded -= AssociatedObjectUnloaded;
    OnCleanup();
    IsCleanedUp = true;
  }
}

protected override void OnDetaching()
{
  Cleanup();
  base.OnDetaching();
}

private void AssociatedObjectUnloaded(object sender, RoutedEventArgs e)
{
  Cleanup();
}

/// &amp;lt;summary&amp;gt;
/// Override this to add your own cleanup
/// &amp;lt;/summary&amp;gt;
protected virtual void OnCleanup()
{
}&lt;/pre&gt;
&lt;p&gt;And once again you see a simple virtual Cleanup you can override. &lt;/p&gt;
&lt;p&gt;I realize this is all very theoretical and technical, and the question you probably have now is – so what is this for and how do you use it? The usage is simple:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You create a MyBehavior&amp;lt;T&amp;gt; that descends from SafeBehavior&amp;lt;T&amp;gt; 
&lt;li&gt;If you want your behavior to re-init when the user navigates back set ListenToPageBackEvent&amp;nbsp; to true in the MyBehavior constructor. But &lt;em&gt;beware&lt;/em&gt;. By its very nature the Navigated event is &lt;em&gt;not&lt;/em&gt; detached. So basically you are leaking memory. Therefore, if you make a &lt;em&gt;lot&lt;/em&gt; of behaviors, like in a game, don’t ever set ListenToPageBackEvent to true.Use with care and moderation. 
&lt;li&gt;You do setting up events in an override of OnSetup 
&lt;li&gt;You do cleaning up of events in an override of OnCleanup 
&lt;li&gt;And if you want to do something extra when the user is navigating back to the page do that in an override of OnParentPageNavigated.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;This makes implementing the Safe Event Detachment ‘pattern‘ way more easy. This new behavior base is now included in my &lt;a href="http://wp7nl.codeplex.com/" target="_blank"&gt;wp7nl library on codeplex&lt;/a&gt; and the source can be found &lt;a href="http://wp7nl.codeplex.com/SourceControl/changeset/view/11210#214132" target="_blank"&gt;here&lt;/a&gt;. A sample usage of this base class can be found &lt;a href="http://dotnetbyexample.blogspot.com/2011/12/rethinking-behavior-to-show-windows.html" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5295746446529817470-1967210838325718409?l=dotnetbyexample.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/dotnetbyexample/~4/d60ZksYrZHg" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2011-12-03T13:46:36.829+01:00</atom:updated><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://dotnetbyexample.blogspot.com/2011/11/safe-event-detachment-base-class-for.html</feedburner:origLink></item><item><title>Using MVVMLight, ItemsControl, Blend and behaviors to make a ‘heads up compass’</title><link>http://feedproxy.google.com/~r/blogspot/dotnetbyexample/~3/9VBqKmh_kAU/when-i-talk-of-mvvm-pattern-people.html</link><category>MVVM</category><category>behavior</category><category>WP7NL</category><category>MVVM Light</category><category>Augmented Reality</category><category>WP7</category><category>DataBinding</category><category>dotnetmag</category><category>Blend</category><author>noreply@blogger.com (Joost van Schaik)</author><pubDate>Tue, 22 Nov 2011 12:36:00 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5295746446529817470.post-5191789389352624796</guid><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/kAprb26D-SD9EP6XyJ9IFpqJ3aI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kAprb26D-SD9EP6XyJ9IFpqJ3aI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/kAprb26D-SD9EP6XyJ9IFpqJ3aI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kAprb26D-SD9EP6XyJ9IFpqJ3aI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;When I talk of the MVVM pattern, people usually think of business objects that get wrapped by ViewModels which get data bound to a user interface. Usually this is something like a list of people, news, items that can be purchased, whatever – and usually this data is displayed in a list box, with a bit of templating if it isn’t too much trouble. That’s fine in itself and good way to use my favorite pattern but there are more things possible using MVVM data binding than most people imagine. The most fun way I have been able to discover is to combine &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol(v=VS.95).aspx" target="_blank"&gt;ItemsControl&lt;/a&gt; and behaviors. This is what drives my game &lt;a href="http://www.windowsphone.com/en-US/apps/48fd8097-f07e-e011-986b-78e7d1fa76f8" target="_blank"&gt;Catch’em Birds&lt;/a&gt;. And this article shows how to use this technique make a kind of heads up compass. I’ll sprinkle some ‘how to do things in Blend’ (like adding and configuring behaviors) throughout the article as well.&lt;/p&gt; &lt;p&gt;For the hasty readers: “Setting the stage”, “Building the models” and “Building the ViewModel” is the ground work. The real stuff starts at “&lt;a href="#IntialUserInterface"&gt;Initial user interface&lt;/a&gt;”.&lt;/p&gt; &lt;p&gt;&lt;font size="4"&gt;Setting the stage&lt;/font&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Create a new &lt;a href="http://www.microsoft.com/windowsphone/" target="_blank"&gt;Windows Phone 7&lt;/a&gt; application. Let’s call it “HeadsUpCompass”. Select Windows Phone 7.1 - duh ;).  &lt;li&gt;Install my &lt;a href="http://wp7nl.codeplex.com/" target="_blank"&gt;wp7nl library from codeplex&lt;/a&gt; via NuGet. This will get you some of my stuff and MVVMLight and some more stuff as well in one go.  &lt;li&gt;Add references to Microsoft.Device.Sensors and Microsoft.Xna.Framework.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;font size="4"&gt;Building the models&lt;/font&gt;&lt;/p&gt; &lt;p&gt;The application has two models: CompassDirectionModel – holding stuff that wants to be displayed, and CompassModel, that checks the compass direction using the motion API. The CompassModel is implemented below. I’ve explained &lt;a href="http://dotnetbyexample.blogspot.com/2011/10/using-motion-api-to-check-what.html" target="_blank"&gt;using the Motion API to check where the camera is looking&lt;/a&gt; in an earlier post so I’ll skip the details here. It’s basically the same functionality, wrapped in a model, with an event firing at the end:&lt;/p&gt;&lt;pre&gt;using System;
using System.Windows;
using Microsoft.Devices.Sensors;
using Microsoft.Xna.Framework;

namespace HeadsUpCompass.Models
{
  public class CompassModel
  {
    Motion motion;

    /// &amp;lt;summary&amp;gt;
    /// Inits this instance.
    /// &amp;lt;/summary&amp;gt;
    public void Init()
    {
      // Check to see if the Motion API is supported on the device.
      if (!Motion.IsSupported)
      {
        MessageBox.Show("the Motion API is not supported on this device.");
        return;
      }

      // If the Motion object is null, initialize it and add a CurrentValueChanged
      // event handler.
      if (motion == null)
      {
        motion = new Motion {TimeBetweenUpdates = TimeSpan.FromMilliseconds(250)};
        motion.CurrentValueChanged += MotionCurrentValueChanged;
      }

      // Try to start the Motion API.
      try
      {
        motion.Start();
      }
      catch (Exception)
      {
        MessageBox.Show("unable to start the Motion API.");
      }
    }

        /// &amp;lt;summary&amp;gt;
    /// Stops this instance.
    /// &amp;lt;/summary&amp;gt;
    public void Stop()
    {
      motion.Stop();
      motion.CurrentValueChanged -= MotionCurrentValueChanged;
    }

    /// &amp;lt;summary&amp;gt;
    /// Fired when a direction change is detected
    /// &amp;lt;/summary&amp;gt;
    void MotionCurrentValueChanged(object sender, 
                                   SensorReadingEventArgs&amp;lt;MotionReading&amp;gt; e)
    {
      var yaw = MathHelper.ToDegrees(e.SensorReading.Attitude.Yaw);
      var roll = MathHelper.ToDegrees(e.SensorReading.Attitude.Roll);
      var pitch = MathHelper.ToDegrees(e.SensorReading.Attitude.Pitch);

      if (roll &amp;lt; -20 &amp;amp;&amp;amp; roll &amp;gt; -160)
      {
        SetNewCompassDirection(360 - yaw + 90);
      }
      else if (roll &amp;gt; 20 &amp;amp;&amp;amp; roll &amp;lt; 160)
      {
        SetNewCompassDirection(360 - yaw - 90);
      }
      else if (pitch &amp;gt; 20 &amp;amp;&amp;amp; pitch &amp;lt; 160)
      {
        SetNewCompassDirection(-yaw );
      }
      else if (pitch &amp;lt; -20 &amp;amp;&amp;amp; pitch &amp;gt; -160)
      {
        SetNewCompassDirection(360 - yaw + 180);
      }
    }

    private void SetNewCompassDirection(double compassDirection)
    {
      if (compassDirection &amp;gt; 360)
      {
        compassDirection -= 360;
      }
      if (compassDirection &amp;lt; 0)
      {
        compassDirection += 360;
      }

      if (CompassDirectionChanged != null)
      {
        CompassDirectionChanged(Convert.ToInt32(Math.Round(compassDirection)));
      }
    }

    // Event communicating compass direction change to outside world
    public event CompassDirectionChangedHandler CompassDirectionChanged;
    
    public delegate void CompassDirectionChangedHandler(int newDirection);
  }
}&lt;/pre&gt;
&lt;p&gt;The stuff that gets displayed has it’s own model, and is very simple:&lt;/p&gt;&lt;pre&gt;using System.Collections.Generic;

namespace HeadsUpCompass.Models
{
  public class CompassDirectionModel
  {
    public int Direction { get; set; }

    public string Text { get; set; }

    public static IEnumerable&amp;lt;CompassDirectionModel&amp;gt; GetCompassDirections()
    {
      return new List&amp;lt;CompassDirectionModel&amp;gt;
      {
        new CompassDirectionModel {Direction = 0, Text = "N"},
        new CompassDirectionModel {Direction = 45, Text = "NE"},
        new CompassDirectionModel {Direction = 90, Text = "E"},
        new CompassDirectionModel {Direction = 135, Text = "SE"},
        new CompassDirectionModel {Direction = 180, Text = "S"},
        new CompassDirectionModel {Direction = 225, Text = "SW"},
        new CompassDirectionModel {Direction = 270, Text = "W"},
        new CompassDirectionModel {Direction = 315, Text = "NW"}
      };
    }
  }
}&lt;/pre&gt;
&lt;p&gt;And most of is a static factory method too that I, being a lazy programmer, just plonked into a class. This model accepts a text and a compass direction where it wants to be displayed. You can limit or add whatever you like.&lt;/p&gt;
&lt;p&gt;&lt;font size="4"&gt;Building the ViewModel&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;So far it has not been quite rocket science, and neither is the only ViewModel that is employed in this solution:&lt;/p&gt;&lt;pre&gt;using System.Collections.ObjectModel;
using System.Windows;
using GalaSoft.MvvmLight;
using HeadsUpCompass.Models;

namespace HeadsUpCompass.ViewModels
{
  public class CompassViewModel : ViewModelBase
  {
    private readonly CompassModel model;

    public CompassViewModel()
    {
      model = new CompassModel();
      model.CompassDirectionChanged += ModelCompassDirectionChanged;
      CompassDirections = 
        new ObservableCollection&amp;lt;CompassDirectionModel&amp;gt;(
          CompassDirectionModel.GetCompassDirections());
      if( !IsInDesignMode) model.Init();
    }

    void ModelCompassDirectionChanged(int newDirection)
    {
      Deployment.Current.Dispatcher.BeginInvoke(
        () =&amp;gt; { CompassDirection = newDirection; });
    }

    private int compassDirection;
    public int CompassDirection
    {
      get { return compassDirection; }
      set
      {
        if (compassDirection != value)
        {
          compassDirection = value;
          RaisePropertyChanged(() =&amp;gt; CompassDirection);
        }
      }
    }

    private ObservableCollection&amp;lt;CompassDirectionModel&amp;gt; compassDirections;
    public ObservableCollection&amp;lt;CompassDirectionModel&amp;gt; CompassDirections
    {
      get { return compassDirections; }
      set
      {
        if (compassDirections != value)
        {
          compassDirections = value;
          RaisePropertyChanged(() =&amp;gt; CompassDirections);
        }
      }
    }
  }
}&lt;/pre&gt;
&lt;p&gt;The ViewModel creates a CompassDirectionModel and subscribes to its events, and fills an observable collection with CompassDirectionModels – so basically a list of texts and the direction in which they want to be displayed. &lt;/p&gt;&lt;a name="IntialUserInterface"&gt;&lt;/a&gt;
&lt;p&gt;&lt;font size="4"&gt;Initial user interface&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;First of all, open MainPage.xaml, set shell:SystemTray.IsVisible="false", SupportedOrientations="PortraitOrLandscape" and then delete the grid “LayoutRoot” and everything inside it (and get rid of the App Bar sample code that commented out as well, that clears the stage). Replace it by this:&lt;/p&gt;&lt;pre&gt;&amp;lt;Grid x:Name="LayoutRoot" &amp;gt;
  &amp;lt;Grid.RowDefinitions&amp;gt;
    &amp;lt;RowDefinition Height="Auto"/&amp;gt;
    &amp;lt;RowDefinition Height="*"/&amp;gt;
  &amp;lt;/Grid.RowDefinitions &amp;gt;

  &amp;lt;!--TitlePanel contains the name of the application and page title--&amp;gt;
  &amp;lt;StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"&amp;gt;
    &amp;lt;TextBlock x:Name="ApplicationTitle" Text="HeadsUp Compass" 
      Style="{StaticResource PhoneTextNormalStyle}"/&amp;gt;
  &amp;lt;/StackPanel&amp;gt;

  &amp;lt;!--ContentPanel - place additional content here--&amp;gt;
  &amp;lt;Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"&amp;gt;
    &amp;lt;Grid&amp;gt;
      &amp;lt;Grid.RowDefinitions&amp;gt;
        &amp;lt;RowDefinition Height="0.7*"/&amp;gt;
        &amp;lt;RowDefinition Height="0.3*"/&amp;gt;
      &amp;lt;/Grid.RowDefinitions &amp;gt;
    &lt;font color="#ff0000"&gt;&amp;lt;ItemsControl x:Name="CompassItems" ItemsSource="{Binding CompassDirections}"
           Grid.Row="0"&amp;gt;
      &amp;lt;ItemsControl.ItemsPanel&amp;gt;
        &amp;lt;ItemsPanelTemplate&amp;gt;
          &amp;lt;Canvas Background="Transparent" /&amp;gt;
        &amp;lt;/ItemsPanelTemplate&amp;gt;
      &amp;lt;/ItemsControl.ItemsPanel&amp;gt;
      &amp;lt;ItemsControl.ItemTemplate&amp;gt;
        &amp;lt;DataTemplate&amp;gt;
          &amp;lt;Grid&amp;gt;
            &amp;lt;TextBlock Text="{Binding Text}" FontSize="48" Foreground="Red"/&amp;gt;
          &amp;lt;/Grid&amp;gt;
        &amp;lt;/DataTemplate&amp;gt;
      &amp;lt;/ItemsControl.ItemTemplate&amp;gt;
    &amp;lt;/ItemsControl&amp;gt;&lt;/font&gt;

    &amp;lt;TextBlock TextWrapping="Wrap" Text="{Binding CompassDirection}" 
       VerticalAlignment="Top" Margin="0,10,0,0" FontSize="48" Foreground="Red" 
       HorizontalAlignment="Center" Grid.Row="1"/&amp;gt;
    &amp;lt;/Grid&amp;gt;
  &amp;lt;/Grid&amp;gt;
&amp;lt;/Grid&amp;gt;&lt;/pre&gt;
&lt;p&gt;The interesting part I’ve marked red. This is an ItemsControl - nothing more than a simple repeater. The declaration used in this article uses two templates: an &lt;em&gt;ItemsPanelTemplate&lt;/em&gt;, which describes what all the bound items are rendered upon – in this case, a transparent canvas – and an &lt;em&gt;ItemTemplate, &lt;/em&gt;which describes how each individual item in the CompassDirections property bound to the control itself is displayed – in this case, a grid with a simple text bound to a Text property. But on the ItemTemplate you can put literally everything you can dream. Including behaviors.&lt;/p&gt;
&lt;p&gt;&lt;font size="4"&gt;Setting up data binding using Expression Blend&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;First let’s get the data binding done. This is considerably easier using Expression Blend. Compile the application so far, and open it up in Expression Blend. Then use the following workflow:&lt;a href="http://lh4.ggpht.com/-0vjOneRdr6U/TswHsjBNTsI/AAAAAAAAHCQ/whAcEd5jLzg/s1600-h/DataSource5.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DataSource" border="0" alt="DataSource" align="right" src="http://lh3.ggpht.com/-EHpu4ufxRHU/TswHtIE-9oI/AAAAAAAAHCU/K34Qv-RhJxc/DataSource_thumb1.png?imgmax=800" width="244" height="84"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;On the top right hand side, select the “Data” tab 
&lt;li&gt;Click the Icon on the right that gives as tooltip “Create data source” 
&lt;li&gt;Select “Create Object DataSource” 
&lt;li&gt;Select “CompassViewModel” in the popup that appears. 
&lt;li&gt;Drag “CompassViewModel” under “CompassViewModelSource on top of the “LayoutRoot” grid in the Objects and Timeline Panel to the left bottom&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://lh4.ggpht.com/-o0_mZyRmdGI/TswHtlFxaUI/AAAAAAAAHCg/g60-I-d5o8c/s1600-h/Bound3.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Bound" border="0" alt="Bound" align="right" src="http://lh6.ggpht.com/-Oty0YwYluOc/TswHus6P61I/AAAAAAAAHCo/UlSTrJXPnYg/Bound_thumb1.png?imgmax=800" width="133" height="217"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you have done things correctly, you should immediately see appear a red zero in the horizontal middle of your screen a little below the center, and a lot of texts stacked upon each other in the top left op your screen. &lt;/p&gt;
&lt;p&gt;The fun thing is, this application already works more or less. If you deploy this on a device and fire it up, you will already see that the 0 starts to display the compass direction in degrees. But the compass direction texts are still stacked upon each other in the top left corner. Now it’s time for the coupe de grâce: a behavior that dynamically changes the location of the compass direction texts.&lt;/p&gt;
&lt;p&gt;&lt;font size="4"&gt;Location calculation&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;The behavior actually consist out of two parts: the LocationCalculator class and the actual CompassDirectionDisplayBehavior. I pulled the actual location calculation out of the behavior because I had to cobble it together by trial and error – and adding it to a test project by means of a link and testing it by unit tests made this a lot easier. Anyway, the code itself it pretty small: most of it is comments and properties:&lt;/p&gt;&lt;pre&gt;using System;
using System.Windows;

namespace ARCompass.Behaviors
{
  /// &amp;lt;summary&amp;gt;
  /// Calculates screen positions based upon compass locations
  /// &amp;lt;/summary&amp;gt;
  public class LocationCalcutator
  {
    /// &amp;lt;summary&amp;gt;
    /// Initializes a new instance of the LocationCalcutator class.
    /// Sets some reasonable defaults
    /// &amp;lt;/summary&amp;gt;
    public LocationCalcutator()
    {
      Resolution = (6 * 800 / 360);
      CanvasHeight = 800;
      CanvasWidth = 480;
      ObjectWidth = 10;
    }

    /// &amp;lt;summary&amp;gt;
    /// Gets or sets the resolution (i.e. the pixels per degree
    /// &amp;lt;/summary&amp;gt;
    public int Resolution { get; set; }

    /// &amp;lt;summary&amp;gt;
    /// The compass direction where the object to calculate for is located
    /// &amp;lt;/summary&amp;gt;
    public int DisplayCompassDirection { get; set; }

    /// &amp;lt;summary&amp;gt;
    /// Gets or sets the width of the canvas.
    /// &amp;lt;/summary&amp;gt;
    public double CanvasWidth { get; set; }

    /// &amp;lt;summary&amp;gt;
    /// Gets or sets the height of the canvas.
    /// &amp;lt;/summary&amp;gt;
    public double CanvasHeight { get; set; }

    /// &amp;lt;summary&amp;gt;
    /// Gets or sets the width of the object (in pixels)
    /// &amp;lt;/summary&amp;gt;
    public double ObjectWidth { get; set; }

    /// &amp;lt;summary&amp;gt;
    /// Sets the horizontal pixels.
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;param name="pixels"&amp;gt;The pixels.&amp;lt;/param&amp;gt;
    public void SetHorizontalPixels(double pixels)
    {
      Resolution = Convert.ToInt32(Math.Round(pixels/360));
    }

    /// &amp;lt;summary&amp;gt;
    /// Calculates the screen position.
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;param name="compassDirection"&amp;gt;The compass direction the screen is 
    /// currently looking at.&amp;lt;/param&amp;gt;
    /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
    public Point CalculateScreenPosition(int compassDirection)
    {
      if (!(double.IsNaN(CanvasHeight) || double.IsNaN(CanvasWidth)))
      {
        var y = CanvasHeight / 2;
        var deltaDegrees1 = compassDirection - DisplayCompassDirection;
        var deltaDegrees2 = compassDirection - DisplayCompassDirection - 360;
        var deltaDegrees = 
           Math.Abs(deltaDegrees1) &amp;lt; Math.Abs(deltaDegrees2) ? 
             deltaDegrees1 : deltaDegrees2;

        var dx = deltaDegrees * Resolution;
        var x = Convert.ToInt32(CanvasWidth / 2) - dx;
        return new Point(x, y);
      }
      return new Point(-1000, -1000);
    }

    /// &amp;lt;summary&amp;gt;
    /// Determines whether the specified point is visible in the current canvas
    /// &amp;lt;/summary&amp;gt;
    public bool IsVisible(Point point)
    {
      var overshoot = Convert.ToInt32(Math.Round(ObjectWidth/2 + 5));
      return (point.X &amp;gt; -overshoot &amp;amp;&amp;amp; point.X &amp;lt; CanvasWidth + overshoot);
    }
  }
}&lt;/pre&gt;
&lt;p&gt;Resolution is a pretty weird property and is the base for all other calculations. It basically says – how many pixels is 1 degree? Default I set it to 6 * 800 / 360 = 13.333, which basically means if you move your camera 1 degree to the left whatever is displayed on your screen moves 13 pixels to the right. &lt;/p&gt;
&lt;p&gt;The CalculateScreenPosition method basically is my way to calculate the screen position of an object in direction compassDirection, without using trigonometry – since I am notoriously bad at it. I’ve learned it about three times if I really have to use it, but for some reason as soon as I stop using it, it quite quickly drops from my mind again. I don’t doubt I’ll be getting reactions of math lovers who will point out this a stupid way to do it ;-). But this works, and that’s fine with me. Finally, the IsVisible property can be used to determine if the objects is on the screen at all.&lt;/p&gt;
&lt;p&gt;&lt;font size="4"&gt;The actual behavior&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;This behavior heavily leans on things I wrote about earlier, namely the extension methods for FrameWorkElement I described in my article&amp;nbsp; “&lt;a href="http://dotnetbyexample.blogspot.com/2011/03/simple-windows-phone-7-silverlight.html"&gt;Simple Windows Phone 7 / Silverlight drag/flick behavior&lt;/a&gt;” but which are now fortunately all in the Wp7nl library. It is also based upon the &lt;a href="http://dotnetbyexample.blogspot.com/2011/04/safe-event-detachment-pattern-for.html"&gt;Safe event detachment ‘pattern’ for behaviors&lt;/a&gt;. Anyway – the base setup is like this:&lt;/p&gt;&lt;pre&gt;using System.Windows;
using System.Windows.Interactivity;
using System.Windows.Media;
using ARCompass.Behaviors;
using Phone7.Fx.Preview;
using Wp7nl.Utilities;

namespace HeadsUpCompass.Behaviors
{
  public class CompassDirectionDisplayBehavior : Behavior&amp;lt;FrameworkElement&amp;gt;
  {
    private FrameworkElement elementToAnimate;

    private FrameworkElement displayCanvas;

    private LocationCalcutator calculator;

    #region Setup
    protected override void OnAttached()
    {
      base.OnAttached();
      AssociatedObject.Loaded += AssociatedObjectLoaded;
      AssociatedObject.Unloaded += AssociatedObjectUnloaded;
    }

    void AssociatedObjectLoaded(object sender, RoutedEventArgs e)
    {
      calculator = new LocationCalcutator 
        {DisplayCompassDirection = DisplayCompassDirection};
      elementToAnimate = AssociatedObject.GetElementToAnimate();
      if (!(elementToAnimate.RenderTransform is CompositeTransform))
      {
        elementToAnimate.RenderTransform = new CompositeTransform();
      }
      displayCanvas = elementToAnimate.GetVisualParent();
      if (displayCanvas != null)
      {
        displayCanvas.SizeChanged += DisplayCanvasSizeChanged;
        UpdateCalculator();
      }
    }
    #endregion

    #region Cleanup
    private bool isCleanedUp;

    private void Cleanup()
    {
      if (!isCleanedUp)
      {
        isCleanedUp = true;
        AssociatedObject.Loaded -= AssociatedObjectLoaded;
        AssociatedObject.Unloaded -= AssociatedObjectUnloaded;
      }
    }

    protected override void OnDetaching()
    {
      Cleanup();
      base.OnDetaching();
    }

    void AssociatedObjectUnloaded(object sender, RoutedEventArgs e)
    {
      Cleanup();
    }
    #endregion
  }
}&lt;/pre&gt;
&lt;p&gt;Now that most of the calculation logic is in the LocationCalculator, the calculation and positioning logic is reduced to these three little methods:&lt;/p&gt;&lt;pre&gt;void DisplayCanvasSizeChanged(object sender, SizeChangedEventArgs e)
{
  UpdateCalculator();
}

private void UpdateCalculator()
{
  calculator.CanvasHeight = displayCanvas.ActualHeight;
  calculator.CanvasWidth = displayCanvas.ActualWidth;
  calculator.SetHorizontalPixels(6 * calculator.CanvasWidth);
  UpdateScreenLocation();
}

void UpdateScreenLocation()
{
  var translationPoint = 
     calculator.CalculateScreenPosition(CurrentCompassDirection);
  if (calculator.IsVisible(translationPoint))
  {
    elementToAnimate.SetTranslatePoint(
      calculator.CalculateScreenPosition(CurrentCompassDirection));
    elementToAnimate.Visibility = Visibility.Visible;
  }
  else
  {
    elementToAnimate.Visibility = Visibility.Collapsed;
  }
}&lt;/pre&gt;
&lt;p&gt;The fun thing is that the calculator’s resolution is set to 6 times the canvas width, so that every time you rotate the phone it recalculates the location where objects are displayed. The net result is that objects are spaced wider apart when you rotate the phone in landscape. Thus, the app makes optimal use of the screen space available.&lt;/p&gt;
&lt;p&gt;And all there is left are two dependency properties: DisplayCompassDirection which holds the location in which the current object wants to be displayed, and CurrentCompassDirection&amp;nbsp; which should get the current direction the camera is looking at. By nature they are pretty verbose unfortunately:&lt;/p&gt;&lt;pre&gt;#region DisplayCompassDirection
public const string DisplayCompassDirectionPropertyName = 
   "DisplayCompassDirection";

public int DisplayCompassDirection
{
  get { return (int)GetValue(DisplayCompassDirectionProperty); }
  set { SetValue(DisplayCompassDirectionProperty, value); }
}

public static readonly DependencyProperty DisplayCompassDirectionProperty = 
  DependencyProperty.Register(
    DisplayCompassDirectionPropertyName,
    typeof(int),
    typeof(CompassDirectionDisplayBehavior),
    new PropertyMetadata(0, null));
#endregion

#region CurrentCompassDirection
public const string CurrentCompassDirectionPropertyName = 
  "CurrentCompassDirection";

public int CurrentCompassDirection
{
  get { return (int)GetValue(CurrentCompassDirectionProperty); }
  set { SetValue(CurrentCompassDirectionProperty, value); }
}

public static readonly DependencyProperty CurrentCompassDirectionProperty =
  DependencyProperty.Register(
    CurrentCompassDirectionPropertyName,
    typeof(int),
    typeof(CompassDirectionDisplayBehavior),
    new PropertyMetadata(0, CurrentCompassDirectionChanged));

public static void CurrentCompassDirectionChanged(
  DependencyObject d, DependencyPropertyChangedEventArgs e)
{
  var behavior = d as CompassDirectionDisplayBehavior;
  if (behavior != null)
  {
    behavior.UpdateScreenLocation();
  }
}
#endregion&lt;/pre&gt;
&lt;p&gt;Save and compile the app. Don’t run it yet.&lt;/p&gt;
&lt;p&gt;&lt;font size="4"&gt;&lt;a href="http://lh6.ggpht.com/-6SOei25OEyE/TswHveZcjhI/AAAAAAAAHCw/6esOVfRLDjY/s1600-h/DragBehavior3.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DragBehavior" border="0" alt="DragBehavior" align="right" src="http://lh5.ggpht.com/-3b6uQVGZvaw/TswHwRYTOOI/AAAAAAAAHC4/ef8x1dK4d8A/DragBehavior_thumb1.png?imgmax=800" width="177" height="313"&gt;&lt;/a&gt;Adding/configuring the behavior using Expression Blend&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;Go back to Expression Blend, and use the following workflow:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In the Objects and Timeline Panel to the left, select ItemsControl “CompassItems” 
&lt;li&gt;Right-click on in, select “Edit Additional Templates”, then “Edit Generated Items (ItemsTemplate)”,&amp;nbsp; and finally “Edit Current” 
&lt;li&gt;Top left, select the “Assets” tab. In the left panel below it, select “Behaviors”. In the right panel you should see “CompassDirectionDisplayBehavior” appear. 
&lt;li&gt;Drag the behavior on top of the grid&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;As soon as you have done this, you will get a properties tab on the right of your screen that neatly shows the two dependency properties. Of course you can do this in code, but Blend takes care of creating namespaces and name space references – it makes life so much easier and that should appeal to a programmer’s natural laziness. Next task is data binding properties of the behavior to the ViewModel, and using Blend that is dead easy too.&lt;/p&gt;
&lt;p&gt;&lt;font size="4"&gt;Configuring behavior binding&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://lh3.ggpht.com/-Pdko64LA0GE/TswHxaAFrgI/AAAAAAAAHDA/N6LLKIYR7gc/s1600-h/behaviorproperties%25255B11%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 5px 0px 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top: 0px; border-right: 0px; padding-top: 0px" title="behaviorproperties" border="0" alt="behaviorproperties" align="left" src="http://lh5.ggpht.com/-yxyFa-z_Umc/TswHySYD1gI/AAAAAAAAHDE/la2iik_LZUI/behaviorproperties_thumb%25255B5%25255D.png?imgmax=800" width="149" height="99"&gt;&lt;/a&gt;Data binding to a behavior, yes sir (or ma’am)! Welcome to Mango: this is Silverlight 4, so no more complex hooplah with attached dependency properties if you want to have a behavior to play along with data binding. You can now directly bind to dependency properties in the behavior itself! After you have dragged the CompassDirectionDisplayBehavior on Grid, you get the little properties tab as displayed on the left, showing the behavior's two properties. To data bind these, use the following workflow:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Click the little square right of “DisplayCompassDirection” (indicated with the red circle), and select “Data Binding” from the popup menu&lt;/li&gt;
&lt;li&gt;Choose tab “Data context” on the dialog that pops us (usually that’s default)&lt;/li&gt;
&lt;li&gt;Select property “Direction : (Int32), that is directly under CompassDirections : (CompassDirectionModel)&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;You have now selected the DisplayCompassDirection property of the behavior to be bound directly to the “Direction” property to the CompassDirectionModel. One can argue if it’s technically corr&lt;a href="http://lh5.ggpht.com/-_wpdI1WHA7E/TswHy1aVaZI/AAAAAAAAHDQ/YARqWWYGdM0/s1600-h/DataBindingDisplayDirection%25255B5%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top: 0px; border-right: 0px; padding-top: 0px" title="DataBindingDisplayDirection" border="0" alt="DataBindingDisplayDirection" align="right" src="http://lh6.ggpht.com/-AgGmuiq0iM4/TswHznwjoOI/AAAAAAAAHDY/j_v-GM4FOos/DataBindingDisplayDirection_thumb%25255B3%25255D.png?imgmax=800" width="248" height="323"&gt;&lt;/a&gt;ect to directly bind a Model in stead of having a ViewModel sitting in between. Since this Model only shows data and has no intelligence at all, I feel comfortable with it – if you do not, go ahead and define a ViewModel around it ;-)&lt;/p&gt;
&lt;p&gt;The second and last part of binding goes like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Click the square behind “CurrentCompassDirection” and select “Data Binding” again in the popup menu&lt;/li&gt;
&lt;li&gt;Select the “Data Field” tab&lt;/li&gt;
&lt;li&gt;In the Data Field Tab, select “CompassViewModelDataSource” in the right pane&lt;/li&gt;
&lt;li&gt;In the left pane, select “CompassDirection : (Int32) &lt;/li&gt;
&lt;li&gt;Click the down-pointing arrow on the bottom of the dialog – more options appear&lt;/li&gt;
&lt;li&gt;Select “TwoWay” for “Binding Direction”&lt;/li&gt;&lt;!--EndFragment--&gt;&lt;/ul&gt;







&lt;p&gt;You have now selected the CurrentCompassDirection property of the behavior to be bound to the CompassDirection of the CompassViewModel. And that means – you are done! Hit File/Save all and go back to Visual Studio to launch the application on your phone, and you will see compass directions moving through your screen if you move phone.&lt;/p&gt;
&lt;p&gt;&lt;font size="4"&gt;One for the road&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;Having a plain black screen to see the compass directions moving over is quite boring. So lets add the &lt;a href="http://dotnetbyexample.blogspot.com/2011/10/behavior-to-show-windows-phone-7-camera.html"&gt;behavior to show the Windows Phone 7 camera as background&lt;/a&gt; I wrote some time ago as well. Add it to the project, drag it on top of the LayoutRoot grid, and bang – now you don’t only have a heads-up, but a see-trough compass as well!&lt;/p&gt;
&lt;p&gt;&lt;font size="4"&gt;Some final words&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;This is all pretty crude in terms of how things move, and there are quite some things eligible for improvement but nevertheless - what we have here is almost like any other old LOB MVVM based application. Business objects bound to the GUI. Only, that GUI happens to be an ItemsControl with a behavior on its template. Which turns the whole app into a dynamic experience. I hope to have tickled your imagination, and showed some useful Blend how-to as well. &lt;/p&gt;
&lt;p&gt;MVVM is not limited to just LOB apps. Make something fun. To quote Nokia – make the amazing everyday ;-&lt;/p&gt;
&lt;p&gt;Complete sample solution can be found &lt;a href="http://www.schaikweb.net/dotnetbyexample/HeadsUpCompass.zip" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5295746446529817470-5191789389352624796?l=dotnetbyexample.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/dotnetbyexample/~4/9VBqKmh_kAU" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2011-12-15T13:45:13.903+01:00</atom:updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/-EHpu4ufxRHU/TswHtIE-9oI/AAAAAAAAHCU/K34Qv-RhJxc/s72-c/DataSource_thumb1.png?imgmax=800" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://dotnetbyexample.blogspot.com/2011/11/when-i-talk-of-mvvm-pattern-people.html</feedburner:origLink></item><item><title>Carpe Lumia!</title><link>http://feedproxy.google.com/~r/blogspot/dotnetbyexample/~3/2L6sTfhgW1Y/carpe-lumia.html</link><category>Nokia</category><category>Off-topic</category><category>Windows Phone 7</category><category>Lumia800</category><category>WP7</category><category>dotnetmag</category><author>noreply@blogger.com (Joost van Schaik)</author><pubDate>Sun, 06 Nov 2011 09:15:00 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5295746446529817470.post-5517961354101043350</guid><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/QjOlRvjISVIVnnIpJyv4UOYMQmY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QjOlRvjISVIVnnIpJyv4UOYMQmY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/QjOlRvjISVIVnnIpJyv4UOYMQmY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QjOlRvjISVIVnnIpJyv4UOYMQmY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;i&gt;Last updated November 10 2011&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;You know that band you used to love when you were in your teens? They really rocked your adolescent years. They rocked like hell. Their concerts where one great party. I would never end. ….except you grew up, the times changed, so did the music, but the band stuck to what made them great. Fame faded, and slowly they disappeared from your sight. Maybe even their CD’s did not make it into your MP3 collection. They lost their mojo. Sometimes they still performed, but you did not know and even less cared. Sic transit gloria mundi. We all have such a band. If you ask politely and promise to keep it a secret, I’ll tell you mine ;-) .&lt;br&gt;&lt;br&gt;Now suppose, just for the sake of this analogy, after years and years this band of yours got back together. Not to do a ‘one more time for old times’ sake or a Live Aid gig, no: they kick out the drug-addicted drummer, recruit two new young guitar players, a few cool babes as extra singers, and team up with a new song writer. They reinvent themselves, make a new album – totally different music than what they did before, but still keeping what made them great – a beautiful performance. They bring out their new album and they TOTALLY rock the charts. &lt;/p&gt; &lt;p&gt;Now if you try to imagine the WTF feeling this would give you, you get an idea what I had for a few moments when I first booted up the &lt;a href="http://www.nokia.co.uk/gb-en/products/phone/lumia800/" target="_blank"&gt;Nokia Lumia 800&lt;/a&gt; that was delivered on November 4. My first four mobile phones were all Nokia – and now &lt;em&gt;this!&lt;/em&gt; Enough poetic mesmerizing, down to business. My thoughts on the Nokia Lumia 800. I’ll just follow the format I used for my &lt;a href="http://dotnetbyexample.blogspot.com/2011/02/htc-7-pro-in-da-house.html" target="_blank"&gt;HTC 7 Pro&lt;/a&gt; to make a fair comparison&lt;/p&gt; &lt;p&gt;&lt;font size="4"&gt;The phone itself&lt;/font&gt;&lt;/p&gt; &lt;p&gt;It’s physical dimensions are 11.5 x 6 x 1 cm according to my own measurements, although I have to allow for a bit of uncertainty on the latter two because a cross-section on this phone would basically be an oval. The back side is convex, &lt;em&gt;and so is the front side&lt;/em&gt;, &lt;em&gt;i.e. the screen&lt;/em&gt;. This gives a very beautiful result. It weights 142 grams, which I don’t think is very much but it feels heavy – although I think &lt;em&gt;solid&lt;/em&gt; would be a better way to describe it. The first thing that strikes – this phone is different from what I am used to in the Windows Phone arena. It’s &lt;em&gt;beautiful. &lt;/em&gt;It has a smooth, streamlined look. And it feels that way, too. Its polycarbonate unibody design feels soft and it has nothing of this plasticy feel so common for these kind of devices. The hardware buttons are freakin’ made of &lt;em&gt;metal &lt;/em&gt;– having used the Lumia for only a short time makes the camera button of the HTC 7 Pro feel like a wobbly piece of plastic on a cheap bubble contact. See below how this looks. Click for larger picture – as with all pictures in this post&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-3vY5DXrJ1EQ/TrbAnfSxS_I/AAAAAAAAG4Y/mMK7o5EpKMU/s1600-h/Lumina2225.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Lumina2" border="0" alt="Lumina2" src="http://lh6.ggpht.com/-6L0IGcaI5rA/TrbAn-489rI/AAAAAAAAG4c/JeiSgQRc7vU/Lumina2_thumb216.jpg?imgmax=800" width="447" height="52"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The USB port is on the top, which I initially thought was very stupid for in-car use. When I attach a charger the plug would stick out of the top of the phone. Turned out I had not thought long enough about it. More about that later.&lt;/p&gt; &lt;p&gt;&lt;font size="4"&gt;Screen&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-bDNMAtQLXMo/TrbAoqr8VsI/AAAAAAAAG4o/C-mzDvgztC0/s1600-h/Lumia17.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Lumia1" border="0" alt="Lumia1" align="right" src="http://lh6.ggpht.com/-R6UuqWZZfLU/TrbApfnSH7I/AAAAAAAAG4w/A0Rl_Lr_e90/Lumia1_thumb5.png?imgmax=800" width="235" height="428"&gt;&lt;/a&gt;Apparently Nokia have used some kind of AMOLED that is not the same as Samsung’s Super AMOLED. Nokia’s take on this is called “ClearBlack”. Black is &lt;em&gt;very&lt;/em&gt; black, even seen from an extreme angle. Combined with the Nokia-only accent color “Nokia Blue” this gives a very beautiful, lively and crisp image on the start screen. The red is really like &lt;em&gt;very burning fiery &lt;/em&gt;red. I don’t know if Omnia 7 users would be as impressed as I am, but coming from the considerably blander looking HTC screens this is nothing short of stunning. The tiles look like they are floating on the screen. Second thing that strikes is the device’s speed. There is a very notable performance increase compared to the HTC 7 Pro. Think Nodo-to-Mango faster. Things are happening at an uncanny speed. New messages in the People Hub are loaded like almost instantly. I suppose this is the faster processor doing its thing.&lt;/p&gt; &lt;p&gt;Another thing about the screen – it is very sensitive. So much actually that I had a little trouble getting the hang of it – I accidently kept selecting messages in the People hub when I just wanted to scroll trough them. But this extreme sensitivity has a rather unexpected bonus for me – combined the convex screen and the enhanced Mango keyboard &lt;em&gt;I can actually touch type on it&lt;/em&gt;. I only managed this with the HTC Titan before – because that is simply big enough to accommodate my big carpenter’s son hands.&lt;/p&gt; &lt;p&gt;I am told the screen is made out of gorilla glass. This is supposed to be pretty scratch resistant. I did not try any destructive tests on it. I will report later on its durability. &lt;/p&gt; &lt;p&gt;&lt;font size="4"&gt;Phone calls&lt;/font&gt;&lt;/p&gt; &lt;p&gt;Made one phone call with my wife. She said I sounded very crisp and and it was better than the HTC 7 Pro. Hello world, welcome to the smartphone that is actually able to make decent phone calls. Well phooey, is anyone impressed? Nokia were already making phones when I was just coming from college so if they had not figured out how to do &lt;em&gt;this&lt;/em&gt; after all this time, they had best started making rubber boots again a long time ago.&lt;/p&gt; &lt;p&gt;&lt;font size="4"&gt;The camera&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-LpVIubBK7Mo/TrbAqLMu4FI/AAAAAAAAG44/bIm04KqSJrw/s1600-h/WP_0000062.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px 4px 0px 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="WP_000006" border="0" alt="WP_000006" align="left" src="http://lh3.ggpht.com/-IVB9GgouhJI/TrbArELIk5I/AAAAAAAAG5A/J82K2o0QI2s/WP_000006_thumb3.jpg?imgmax=800" width="169" height="245"&gt;&lt;/a&gt;The first thing that struck me about the camera is that there’s a &lt;em&gt;lot&lt;/em&gt; more options in the camera menu than I was used to, like Contrast, Saturation, Focus Mode, ISO, Exposure Mode and White Balance. I took this pretty autumn scene picture with it and I think that looks pretty good. Like I said in my review of the HTC 7 Pro, I am a photographer too and if I take pictures I care about I use a Canon EOS 400 DSLR, so in my book pictures taken by any mobile phone are all, well, let’s keep this polite ;-). Having said that: if I zoom in on pictures made by my HTC 7 Pro I can zoom in about twice before things start to become grainy. Lumia 800: &lt;em&gt;seven&lt;/em&gt; times. Nokia wins this hands-down. But that’s from my old phone. I have no comparison with other new phones. I have heard quite mixed results from this.&lt;/p&gt; &lt;p&gt;I also took a few pictures of flowers close by but that did not work out at all. Only later I found out that this probably has to do with the default Focus mode – that’s Macro, and then apparently it does not want to focus on things close by.&lt;/p&gt; &lt;p&gt;&lt;font size="4"&gt;Sound&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-kPOenM-a6bE/TrbAr_9RlCI/AAAAAAAAG5E/tgb_hmex31U/s1600-h/Lumia35.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Lumia3" border="0" alt="Lumia3" align="right" src="http://lh5.ggpht.com/-9UXc1O3KXlQ/TrbAsfsJReI/AAAAAAAAG5Q/wW2zjhI4-vc/Lumia3_thumb2.jpg?imgmax=800" width="393" height="98"&gt;&lt;/a&gt;I think the best way to describe the sound that comes out of that tiny little speaker on the bottom is something among the lines of “HOLY C…!!!”. I played my little game of &lt;a href="http://www.windowsphone.com/en-US/apps/48fd8097-f07e-e011-986b-78e7d1fa76f8" target="_blank"&gt;Catch’em Birds&lt;/a&gt;. When you slam a bird into a cage, it gives a kind of metallic clang, trying to convey the idea of a metal cage door closing behind the bird. On the Lumia 800 this actually sounds more like a &lt;em&gt;vault&lt;/em&gt; slamming shut. This device makes a pretty decent stand alone music player. Which has a flip side, too – I played Hydro Thunder Go on it and, well, er, the excellent speaker mercilessly reveals the game sounds effects are actually pretty low quality. But I can hardly blame Nokia for that ;-)&lt;/p&gt; &lt;p&gt;&lt;font size="4"&gt;Miscellaneous&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-j906aXBc4iE/TrbAtNljnAI/AAAAAAAAG5U/tYkdIWvTUqU/s1600-h/Lumia44.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Lumia4" border="0" alt="Lumia4" align="right" src="http://lh5.ggpht.com/-uqhcEGSe_0o/TrbAtQ4N0FI/AAAAAAAAG5c/TVD66pMBUb4/Lumia4_thumb1.jpg?imgmax=800" width="325" height="243"&gt;&lt;/a&gt;The nice blue box it comes in contains the standard equipment, i.e. an USB charger with detachable cable (so it can be used to connect the phone to Zune as well), a pair of headphones, a box of manuals in various languages (still unread *cough*) and a silicon case. It actually fits like a glove, and is in the same color as the phone’s body. I suppose it’s for protecting the phone’s shell, but it eludes me from what exactly, since the phone itself is made from a material used in the helmets ice hockey players wear. My wife suggested it was for preventing the floor tiles to crack when you drop a Lumia 800 on it ;-). I also heard these cases will come in different colors, and if that is the case I am so much going to get a blue one ;-). [Note: the blueish reflection of the screen is a side effect of the flash, you don't see this in real life - I just wanted to emphasize the silicon case]&lt;/p&gt; &lt;p&gt;The headphones are kinda cheap and don’t to the phone’s music playing capabilities much justice. For those who want better sound quality, Nokia makes &lt;a href="http://europe.nokia.com/find-products/accessories/headsets/stereo-wired-headsets/nokia-purity-hd-by-monster" target="_blank"&gt;these amazing Monster headsets&lt;/a&gt; that are a much better match for the phone. &lt;/p&gt; &lt;p&gt;&lt;font size="4"&gt;Software and extra’s&lt;/font&gt;&lt;/p&gt; &lt;p&gt;No review of a Lumia 800 would be complete without the on-board extra’s. First of all – we got the genuine iconic, nay, legendary&lt;strong&gt; Nokia ringtone&lt;/strong&gt; and SMS alert. Played on a xylophone. Very nice. For now I selected all the Nokia sounds as a default, just for the heck of it. &lt;/p&gt; &lt;p&gt;Then we have &lt;strong&gt;Nokia Drive&lt;/strong&gt;. Say hello to free turn-by-turn navigation &lt;em&gt;with downloadable maps and voice directions&lt;/em&gt;. I don’t know if it’s actually completely world wide, but if I select Manage Maps/Install, I first have to select which &lt;em&gt;continent&lt;/em&gt; I want maps to install for: Africa, America, Asia, Australia/Oceania and Europe. Drilling down reveals Russia is in there. &lt;em&gt;China&lt;/em&gt; is in there. South America is in there too - including Argentina which does not even have a Marketplace, and the &lt;em&gt;Cayman Islands&lt;/em&gt; for heavens’ sake. If works &lt;em&gt;way&lt;/em&gt; better than Bing Maps directions, and it’s free! And what’s even better – it supports landscape mode, so you can turn your phone sideways and have wide angle navigation. And then the penny dropped – maybe &lt;em&gt;this&lt;/em&gt; is why the USB port is on top, for if you use it for navigation you rotate it 90° and &lt;em&gt;then&lt;/em&gt; the USB port is conveniently pointing sideways for the car charger. &lt;/p&gt; &lt;p&gt;The current version of Nokia Drive still needs an online connection for finding addresses and Points of Interest, but at the Tweakers event at November 9 in Amsterdam Nokia revealed an update that supports total offline navigation will be available very soon. So I guess it's time to kiss my old TomTom goodbye. The Germans have a very good saying about this, attributed to &lt;a href="http://www.60xdeutschland.de/wer-zu-spat-kommt-den-bestraft-das-leben/" target="_blank"&gt;Mikhail Gorbachev: “Wer zu spät kommt, den bestraft das Leben”&lt;/a&gt; (life punishes those who are too late)&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Nokia Maps&lt;/strong&gt; – can’t say much about this; what I currently have on my phone is a very early beta that is obviously not ready yet, but it seems to be a non-driver’s map application for finding your way around. You know? Like Local Scout, but one that does work in Europe? As a GIS developer I very much wonder if this can be extended and used like the Bing maps control in custom applications. I am not sure if this will eventually work completely offline as well.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Nokia Music&lt;/strong&gt; – reminds me of what I saw from Pandora before us Europeans got kicked out. Stream music from a multitude of pre-defined ‘stations’ and you can buy and download stuff from Nokia’s MP3 store if you like. Yesterday I just turned it on “80’s rock” and let it go for hours on end. You can skip a limited number of songs you don’t like. The price of listening: zilch. Nada. Nothing. No pass required, no subscription required. &lt;em&gt;Booya Nokia! &lt;/em&gt;Does this compete with Zune? Like hell it does – if we could &lt;em&gt;get&lt;/em&gt; Zune here. Zune is available in like, 8 countries? Nokia music in a little short of 40, if I am correct. In the mean time – this is &lt;em&gt;great&lt;/em&gt; news for all people outside the Zune coverage area. But beware – this eats a lot of data. &lt;em&gt;Don’t &lt;/em&gt;run this over your 3G connection unless your unlimited plan is really unlimited. The software specifically warns you for that on first startup.&lt;/p&gt; &lt;p&gt;&lt;font size="4"&gt;Room for improvement&lt;/font&gt;&lt;/p&gt; &lt;p&gt;Nokia have gone out on a limb to make the ultimate &lt;a href="http://www.microsoft.com/windowsphone/" target="_blank"&gt;Windows Phone 7&lt;/a&gt; and I think they came pretty far – but there is still room for improvement. From a hardware standpoint, it lacks two features, which by now everyone has heard of:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;No front facing camera  &lt;li&gt;No gyro&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Now the gyro is a feature that the proverbial Iowa soccer mom ain’t&amp;nbsp; gonna miss – the camera is going to hurt if indeed Skype comes to Windows Phone 7. Although I also wonder how much it will actually hurt – I’ve had a video call capable phone for 2.5 years and only used this feature it 3 times – to demo it. I have no idea how much iPhone users actually use FaceTime all the time. &lt;/p&gt; &lt;p&gt;I think Nokia could also look into bringing out a model with more storage aboard. It now ‘only’ has 16GB of storage, which is more than enough for my podcasts, photo’s and music (I may be just weird but I don’t go carrying around enormous music libraries) but apparently there are people need more these days. &lt;/p&gt; &lt;p&gt;Personally I would like also like to have seen a somewhat larger screen.&lt;/p&gt; &lt;p&gt;&lt;font size="4"&gt;The verdict&lt;/font&gt;&lt;/p&gt; &lt;p&gt;I shelled out €562 to get a Windows Phone 7 with keyboard from the UK to the Netherlands only 8 months ago. I am a die hard physical keyboard phone user. After playing with the Nokia Lumia 800 for only 48 hours, I transferred all my stuff to it and shut down the HTC 7 Pro. Sorry old workhorse. You did well. I know I am going to miss the keyboard sometimes, but the screen colors, the relative sluggish response, the already battered plastic shell, the ablating battery case… it’s just no match for this design beastie.&lt;/p&gt; &lt;p&gt;If you want a phone that supports all the latest Windows Phone 7 hardware features, buy something else. There is plenty of choice. That’s the fun thing of Windows Phone 7 – there is a baseline quality, they’re basically all good, and you &lt;em&gt;do &lt;/em&gt;have a choice. One size does not fit all – as for instance the HTC Titan shows quite literally. If you want a really well designed, durable and smart looking, and not overly large Windows Phone 7 device with some very nice free extra’s that’s available at a pretty aggressive price point, by all means, buy the Lumia 800. Especially the blue one. I predict that is going to be a phone you can put on the table and &lt;em&gt;everyone&lt;/em&gt; will know what it is – pretty soon.&lt;/p&gt; &lt;p&gt;&lt;font size="4"&gt;Concluding thoughts&lt;/font&gt;&lt;/p&gt; &lt;p&gt;If this is what Nokia can crank out in 8 months, I really wonder what will happen in 2012. But even more important than &lt;em&gt;what&lt;/em&gt; they crank out, is &lt;em&gt;how&lt;/em&gt; they do it. They really got their marketing act together, and it looks like we are finally going to see some serious marketing for the Windows Phone 7 environment. I see posters, dummy’s and demo models of actual Windows Phone 7 devices appearing in shops. Someone from the &lt;a href="http://twitter.com/#!/search/%23wp7nl" target="_blank"&gt;#wp7nl&lt;/a&gt; gang who has a Lumia too walked into a Vodafone shop to get a microsim and the staff &lt;em&gt;all&lt;/em&gt; recognized the phone immediately. &lt;/p&gt; &lt;p&gt;The time for Windows Phone 7 being an ‘underground’ phone platform is over!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5295746446529817470-5517961354101043350?l=dotnetbyexample.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/dotnetbyexample/~4/2L6sTfhgW1Y" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2011-11-11T10:22:09.501+01:00</atom:updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/-6L0IGcaI5rA/TrbAn-489rI/AAAAAAAAG4c/JeiSgQRc7vU/s72-c/Lumina2_thumb216.jpg?imgmax=800" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://dotnetbyexample.blogspot.com/2011/11/carpe-lumia.html</feedburner:origLink></item><item><title>So what about Windows Phone 7 adoption rates?</title><link>http://feedproxy.google.com/~r/blogspot/dotnetbyexample/~3/ujk0eGN-qeA/so-what-about-windows-phone-7-adoption.html</link><category>Off-topic</category><category>WP7NL</category><category>Windows Phone 7</category><category>WP7</category><category>dotnetmag</category><author>noreply@blogger.com (Joost van Schaik)</author><pubDate>Sun, 30 Oct 2011 11:49:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5295746446529817470.post-7128398244447039880</guid><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/kX5rdr4ZqJLBeBT7PYu0Ejb6UgY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kX5rdr4ZqJLBeBT7PYu0Ejb6UgY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/kX5rdr4ZqJLBeBT7PYu0Ejb6UgY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kX5rdr4ZqJLBeBT7PYu0Ejb6UgY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;“There are three kinds of lies: lies, damned lies and statistics” (Benjamin Disraeli)&lt;/em&gt;&lt;/p&gt; &lt;p&gt;There is a nifty little &lt;a href="http://www.microsoft.com/windowsphone/" target="_blank"&gt;Windows Phone 7&lt;/a&gt; app out there called “&lt;a href="http://www.windowsphone.com/en-us/apps/16b4f331-e05b-e011-854c-00237de2db9e" target="_blank"&gt;…I’m a WP7&lt;/a&gt;”, made by a person who calls himself “Liquid Daffodil”. It’s a bit hard to describe what its actual purpose is. It’s got a lot of features: it can show other people using the same app nearby on a map or a list, it’s got a forum in it, you can send messages to each other, you can see who is developer (or claims to be) and who is not, you can see Xbox avatars, it’s got news about Windows Phone, it also shows you in which ‘hive’ you are (I still don’t quite get that) – anyway, if I may name a main purpose it seems to be you can proudly flag you are a Windows Phone 7 user – but only to &lt;em&gt;other&lt;/em&gt; Windows Phone users running the same app. Its subtitle is “join the movement”. &lt;/p&gt; &lt;p&gt;That may not sound very useful but there is this one thing – it’s got a little option called “statistics”. It shows how much people are using this app, both worldwide and in your country, and how much are claiming to be developers. I’ve been tracking these statistics for the last 14 days and ended up with the following results:&lt;/p&gt;&lt;a href="http://lh5.ggpht.com/-5W957Pn4ias/Tq2cTKYjDcI/AAAAAAAAG34/kW0umsuz_DQ/s1600-h/image%25255B1%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-qZi_cZpwmG8/Tq2cTidXVVI/AAAAAAAAG38/O_ohsayGDAQ/image_thumb.png?imgmax=800" width="563" height="384"&gt;&lt;/a&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-O8sLI8n0ix8/Tq2cUGMYe7I/AAAAAAAAG4E/SFU8Ynoqj0Y/s1600-h/image5%25255B1%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-RU9stV1UEAw/Tq2cU0d9xsI/AAAAAAAAG4M/scpiBmEDXgE/image5_thumb.png?imgmax=800" width="565" height="395"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Left axis shows number of users, right axis number of people who claim to be developers.&lt;/p&gt; &lt;p&gt;I only show these numbers, and I leave interpretation to the reader’s responsibility and wisdom. I would like to point out these are the usage rates of a single app over 14 days, from an unverifiable source (which, if they are true, I am &lt;em&gt;very &lt;/em&gt;jealous of). There are some oddities in it, like the number of Dutch users claiming to be developer actually &lt;em&gt;dropping&lt;/em&gt; and then sharply rising. I show them anyway, if only to show that I am not only sharing things I would &lt;em&gt;like&lt;/em&gt; to see. But I would also like to point out that &lt;em&gt;apparently,&lt;/em&gt; in only &lt;em&gt;14&lt;/em&gt; days worldwide usage &lt;em&gt;of this app&lt;/em&gt; rose with a staggering 23%, the number of people claiming to be developers worldwide with 18%. For the Netherlands the numbers are 25% and 13%. &lt;/p&gt; &lt;p&gt;So what does this say about the actual adoption rate of Windows Phone 7 as a whole, as I so provocatively called this article? Well, basically &lt;em&gt;nothing at all&lt;/em&gt;. How hard is this data? How many % of the total users and developers are actually running this App? How reliable is the developer’s tracking system? Is he telling the truth at all? I can only speculate, and on speculation I got a very good advice from a fellow MVP whose words I tend to take for wisdom, which basically was: “don’t speculate”. It only shows that there &lt;em&gt;seems&lt;/em&gt; to be growth – and quite substantial growth, too. If this bears any kind of correlation with the actual growth of the Windows Phone 7 as a platform life will be interesting indeed :-)&lt;/p&gt; &lt;p&gt;It shows another thing: I really s*ck at making Excel charts. My sincere apologies ;-)&lt;/p&gt; &lt;p&gt;For the record, I wish to state that I have not been given insight in any actual Windows Phone 7 usage data. Microsoft is not telling these things, not even to a Phone Development MVP. As to why this is, once again one can only speculate, which I was advised not to do, so I don’t. I just used publicly available data.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5295746446529817470-7128398244447039880?l=dotnetbyexample.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/dotnetbyexample/~4/ujk0eGN-qeA" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2011-10-30T20:28:32.199+01:00</atom:updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/-qZi_cZpwmG8/Tq2cTidXVVI/AAAAAAAAG38/O_ohsayGDAQ/s72-c/image_thumb.png?imgmax=800" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://dotnetbyexample.blogspot.com/2011/10/so-what-about-windows-phone-7-adoption.html</feedburner:origLink></item><item><title>Using the motion API to check what direction the camera is looking</title><link>http://feedproxy.google.com/~r/blogspot/dotnetbyexample/~3/4RVj3bXUz4o/using-motion-api-to-check-what.html</link><category>WP7NL</category><category>Windows Phone 7</category><category>wpdev</category><category>WP7</category><category>dotnetmag</category><author>noreply@blogger.com (Joost van Schaik)</author><pubDate>Fri, 21 Oct 2011 09:11:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5295746446529817470.post-2009577325286533936</guid><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/mNmMAOPtXHywpqBp57o_OzcsRYs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mNmMAOPtXHywpqBp57o_OzcsRYs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/mNmMAOPtXHywpqBp57o_OzcsRYs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mNmMAOPtXHywpqBp57o_OzcsRYs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Recently I had my very first real try with the &lt;a href="http://www.microsoft.com/windowsphone/" target="_blank"&gt;Windows Phone 7&lt;/a&gt; Motion API, using the Simple Motion Sample and the Augmented Reality Motion Sample which both can be found &lt;a href="http://msdn.microsoft.com/en-us/library/ff431744(v=vs.92).aspx" target="_blank"&gt;here&lt;/a&gt;. Especially the motion API gave results that I found initially very puzzling. My idea was to find out where direction in which the camera is pointing – regardless of how the user holds his phone. Life then becomes pretty interesting. As long a you hold your phone in the standard upright portrait direction, things are pretty simple – Yaw direction is more or less the negative of compass direction – as far as the direction in which the camera is looking is concerned. But if the user holds his phone upside down or in landscape mode, you have to account for the fact that although the &lt;em&gt;camera&lt;/em&gt; is pointing in the same direction, the &lt;em&gt;top&lt;/em&gt; of the phone is pointing in another direction!&lt;/p&gt; &lt;p&gt;I found the following line of reasoning to be fairly correct:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;If Roll is around –90 degrees, the user is holding his phone in landscape mode with the phone top to the left. This is similar to PageOrientation.LandscapeLeft. Compass direction = 360 - yaw + 90 degrees.  &lt;li&gt;If Roll is around 90 degrees the user is holding his phone in landscape mode with the phone top the right. This is similar to PageOrientation.LandscapeRight. Compass direction = 360 – yaw - 90.&lt;!--EndFragment--&gt;  &lt;li&gt;If Pitch is about 90 degrees and Roll around 0, the user is holding the phone in portrait mode and upright. This is similar to PageOrientation.PortraitUp. Compass direction =&amp;nbsp; -yaw.  &lt;li&gt;If Pitch is about -90 degrees and Roll about 0, then the user is holding the phone in portrait mode and upside down. This is similar to PageOrientation.PortraitDown. &lt;br&gt;Compass direction = 360 - yaw + 180. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;In code I translated this as follows:&lt;/p&gt;&lt;pre&gt;public int GetCameraViewDirection(SensorReadingEventArgs&lt;motionreading&gt; e)
{
  var yaw = MathHelper.ToDegrees(e.SensorReading.Attitude.Yaw);
  var roll = MathHelper.ToDegrees(e.SensorReading.Attitude.Roll);
  var pitch = MathHelper.ToDegrees(e.SensorReading.Attitude.Pitch);

  if (roll &amp;lt; -20 &amp;amp;&amp;amp; roll &amp;gt; -160)
  {
    return Normalize(360 - yaw + 90);
  }
  else if (roll &amp;gt; 20 &amp;amp;&amp;amp; roll &amp;lt; 160)
  {
    return Normalize(360 - yaw - 90);
  }
  else if (pitch &amp;gt; 20 &amp;amp;&amp;amp; pitch &amp;lt; 160)
  {
    return Normalize(-yaw );
  }
  else if (pitch &amp;lt; -20 &amp;amp;&amp;amp; pitch &amp;gt; -160)
  {
    return Normalize(360 - yaw + 180);
  }
  
  // No sensible data
  return -1; 
}

private int Normalize( int compassDirection )
{      
  if (compassDirection &amp;gt; 360)
  {
    compassDirection -= 360;
  }
  if (compassDirection &amp;lt; 0)
  {
    compassDirection += 360;
  }
  return compassDirection;
}&lt;/pre&gt;
&lt;p&gt;The MathHelper, by the way, comes from Microsoft.Xna.Framework. If you don’t like my ‘easy way out’ way of returning –1, throw an exception if you like. The Normalize function always makes sure the result is always between 0 and 360 degrees.&lt;/p&gt;
&lt;p&gt;There are some interesting considerations. For example, if you can trap the “OnPageOrientationChanged” event and check it’s value, why then even check pitch and roll? Well, one important reason is that PageOrientation.PortraitDown for some reason is not supported. Try it – use any App supporting Landscape and Portrait. Hold your phone in portrait mode upside (i.e. with the phone top pointing to the floor… nothing happens). &lt;/p&gt;
&lt;p&gt;I also noticed that in the first two cases any value coming from Pitch can best be ignored, because it varies wildly on my phone. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5295746446529817470-2009577325286533936?l=dotnetbyexample.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/dotnetbyexample/~4/4RVj3bXUz4o" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2011-10-21T20:25:23.469+02:00</atom:updated><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://dotnetbyexample.blogspot.com/2011/10/using-motion-api-to-check-what.html</feedburner:origLink></item><item><title>A behavior to show the Windows Phone 7 camera as background</title><link>http://feedproxy.google.com/~r/blogspot/dotnetbyexample/~3/eq1IqJ6_KV4/behavior-to-show-windows-phone-7-camera.html</link><category>behavior</category><category>WP7NL</category><category>Windows Phone 7</category><category>wpdev</category><category>WP7</category><category>dotnetmag</category><author>noreply@blogger.com (Joost van Schaik)</author><pubDate>Mon, 17 Oct 2011 12:31:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5295746446529817470.post-494862941005176815</guid><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/pJdzRpq5YokDbkcmRHsu3dhMRM8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pJdzRpq5YokDbkcmRHsu3dhMRM8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/pJdzRpq5YokDbkcmRHsu3dhMRM8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pJdzRpq5YokDbkcmRHsu3dhMRM8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;This article was updated October 29, 2011, implementing correctly handling of “back” navigation&lt;/em&gt;&lt;/p&gt; &lt;p&gt;In a previous post I showed how to &lt;a href="http://dotnetbyexample.blogspot.com/2011/09/mango-augmented-reality-101-showing.html" target="_blank"&gt;use the camera feed as background on a page&lt;/a&gt; of a &lt;a href="http://www.microsoft.com/windowsphone/" target="_blank"&gt;Windows Phone 7&lt;/a&gt; application. Today, I make it even easier for the really &lt;em&gt;really&lt;/em&gt; lazy programmer: I have created a behavior to do the same. As a bonus, this behavior also takes the page orientation into account and whether the &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.shell.systemtray(v=vs.92).aspx" target="_blank"&gt;SystemTray&lt;/a&gt; is visible or not.&lt;/p&gt; &lt;p&gt;First order of business: make a basic behavior. Using the snippet from my previous &lt;a href="http://dotnetbyexample.blogspot.com/2011/04/safe-event-detachment-pattern-for.html" target="_blank"&gt;safe event detachment pattern for behaviors&lt;/a&gt; the initial setup looks like this:&lt;/p&gt;&lt;pre&gt;namespace Wp7nl.Behaviors
{
  /// &amp;lt;summary&amp;gt;
  /// A behavior that shows a camera view on the background of a panel
  /// &amp;lt;/summary&amp;gt;
  public class CameraViewBackgroundBehavior : Behavior&amp;lt;Panel&amp;gt;
  {
    private PhotoCamera camera;
    private PhoneApplicationFrame parentPage;
    private Uri pageSource;
    private VideoBrush backgroundBrush;

    // Setup and cleanup according to http://bit.ly/dZb6D9

    #region Setup
    protected override void OnAttached()
    {
      base.OnAttached();
      AssociatedObject.Loaded += AssociatedObjectLoaded;
      AssociatedObject.Unloaded += AssociatedObjectUnloaded;
    }

    private void AssociatedObjectLoaded(object sender, RoutedEventArgs e)
    {
      DoInit();
    }
    #endregion

    #region Cleanup
    private bool isCleanedUp;

    private void Cleanup()
    {
      if (!isCleanedUp)
      {
        isCleanedUp = true;
        AssociatedObject.Loaded -= AssociatedObjectLoaded;
        AssociatedObject.Unloaded -= AssociatedObjectUnloaded;
        DoCleanup();
      }
    }

    protected override void OnDetaching()
    {
      Cleanup();
      base.OnDetaching();
    }

    private void AssociatedObjectUnloaded(object sender, RoutedEventArgs e)
    {
      Cleanup();
    }
    #endregion
  }
}&lt;/pre&gt;With sincere apologies to region haters ;-). Nothing special here, just a skeleton behavior on a Panel. From the AssociatedObjectLoaded a method "DoInit" is called, which does actually all that’s needed to get this behavior going:&lt;pre&gt;/// &amp;lt;summary&amp;gt;
/// Initializes the behavior
/// &amp;lt;/summary&amp;gt;
private void DoInit()
{
  // Find the page this control is on and listen to its orientation changed events
  if( parentPage == null)
  {
    parentPage = Application.Current.RootVisual as PhoneApplicationFrame;
    pageSource = parentPage.CurrentSource;
    parentPage.Navigated += ParentPageNavigated;
  }  
  parentPage.OrientationChanged += ParentPageOrientationChanged;

  camera = new PhotoCamera();

  // Create a video brush with the right parameters
  backgroundBrush = new VideoBrush();
  backgroundBrush.Stretch = Stretch.UniformToFill;
  backgroundBrush.AlignmentX = AlignmentX.Left;
  backgroundBrush.AlignmentY = AlignmentY.Top;

  // Set the video brush to the background of the panel 
  // and do an initial display
  AssociatedObject.Background = backgroundBrush;
  backgroundBrush.SetSource(camera);
  SetVideoOrientation(parentPage.Orientation);
}&lt;/pre&gt;
&lt;p&gt;The comments in the source show pretty much what it does: it starts listening to page orientation change events, it sets up the video brush (but now from code in stead of from XAML) and sets the brush to the background of the panel. &lt;/p&gt;
&lt;p&gt;Of course, it has its counterpart disabling all settings again: &lt;/p&gt;&lt;pre&gt;/// &amp;lt;summary&amp;gt;
/// Safely detach all extra events
/// &amp;lt;/summary&amp;gt;
private void DoCleanup()
{
  parentPage.OrientationChanged -= ParentPageOrientationChanged;
  camera.Dispose();
}&lt;/pre&gt;
&lt;p&gt;To make sure the behavior initializes correctly again when the user navigates &lt;em&gt;back&lt;/em&gt; to the page with this behavior on it, the following code is needed (and this is the part I missed myself in the first version of this post)&lt;pre&gt;/// &amp;lt;summary&amp;gt;
/// Re-init when user navigates back to this page
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="sender"&amp;gt;&amp;lt;/param&amp;gt;
/// &amp;lt;param name="e"&amp;gt;&amp;lt;/param&amp;gt;
private void ParentPageNavigated(object sender, NavigationEventArgs e)
{
  if (e.NavigationMode == NavigationMode.Back &amp;&amp; e.Uri.Equals(pageSource))
  {
    isCleanedUp = false;
    AssociatedObject.Loaded += AssociatedObjectLoaded;
    AssociatedObject.Unloaded += AssociatedObjectUnloaded;
  }
}&lt;/pre&gt;
&lt;p&gt;I appears a behavior’s OnAttached is not called when a user navigates back to a page, resulting in the video not being displayed on the background. Anyway, to wrap up the code, you simply need this:&lt;/p&gt;&lt;pre&gt;private void ParentPageOrientationChanged(object sender, 
                                          OrientationChangedEventArgs e)
{
  SetVideoOrientation(e.Orientation);
}

/// &amp;lt;summary&amp;gt;
/// Sets background video brush parameters based upon page orientation
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="orientation"&amp;gt;&amp;lt;/param&amp;gt;
private void SetVideoOrientation(PageOrientation orientation)
{
  System.Diagnostics.Debug.WriteLine("Switching to {0}", orientation);
  switch (orientation)
  {
  case PageOrientation.PortraitUp:
    backgroundBrush.Transform = 
      new CompositeTransform { Rotation = 90, TranslateX = 480 };
    break;
  case PageOrientation.LandscapeLeft:
    backgroundBrush.Transform = null;
    break;
  case PageOrientation.LandscapeRight:
    if (Microsoft.Phone.Shell.SystemTray.IsVisible)
    {
    backgroundBrush.Transform = 
      new CompositeTransform { Rotation = 180, TranslateX = 728, TranslateY = 480 };
    }
    else
    {
    backgroundBrush.Transform = 
      new CompositeTransform { Rotation = 180, TranslateX = 800, TranslateY = 480 };
    }
    break;
  }
}&lt;/pre&gt;
&lt;p&gt;Based upon the way the page is oriented, a different translation and/or rotation is applied. The number are easy enough to recognize, 800 being the vertical resolution and 480 the horizontal resolution of a Windows Phone 7 screen. Apparently a system tray takes about 62 pixels – at least, that was the value I got by trial-and-error till the camera view filled the whole screen background. Bear in mind that although this will probably work on any panel, the numbers only make sense if you add this behavior to it’s top panel.&lt;/p&gt;
&lt;p&gt;Now its simply a matter of dragging this behavior on top of your top panel using expression Blend, and boom – instant camera background. No coding necessary, and a clean and empty code behind file. You big coder hero makes friends with designer ;-)&lt;/p&gt;
&lt;p&gt;Code file can be downloaded &lt;a href="http://www.schaikweb.net/dotnetbyexample/CameraViewBackgroundBehavior.zip" target="_blank"&gt;here&lt;/a&gt;. I will soon add this to the &lt;a href="http://wp7nl.codeplex.com/" target="_blank"&gt;wp7nl library on codeplex&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5295746446529817470-494862941005176815?l=dotnetbyexample.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/dotnetbyexample/~4/eq1IqJ6_KV4" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2011-10-29T09:56:54.311+02:00</atom:updated><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://dotnetbyexample.blogspot.com/2011/10/behavior-to-show-windows-phone-7-camera.html</feedburner:origLink></item><item><title>Taking screenshots with Windows Phone 7 applications using a video feed</title><link>http://feedproxy.google.com/~r/blogspot/dotnetbyexample/~3/RAaZqgrnkIo/taking-screenshots-with-windows-phone-7.html</link><category>xam</category><category>WP7NL</category><category>XAML</category><category>Windows Phone 7</category><category>Augmented Reality</category><category>wpdev</category><category>WP7</category><category>dotnetmag</category><author>noreply@blogger.com (Joost van Schaik)</author><pubDate>Sat, 08 Oct 2011 03:18:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5295746446529817470.post-6443499404109428068</guid><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/9SFO6nhHuCzJI20Cv0U0-BQGPaM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/9SFO6nhHuCzJI20Cv0U0-BQGPaM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/9SFO6nhHuCzJI20Cv0U0-BQGPaM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/9SFO6nhHuCzJI20Cv0U0-BQGPaM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The Marketplace screenshot tool that came with the Windows Phone 7.1 SDK made life for developers a whole lot easier. But suppose you want to enable users to make screenshots from their application in action? This article shows you how.&lt;/p&gt; &lt;p&gt;First of all, the easy part. The framework allows you to make a screen capture by making a WriteableBitmap from a user interface element in a pretty simple way. Create a new Windows Phone application, and select framework version 7.1. Then add a reference to Microsoft.Xna.Framework.dll. Enter the following XAML in your MainPage.xaml&lt;/p&gt;&lt;pre&gt;&amp;lt;Grid x:Name="LayoutRoot"&amp;gt;
  &amp;lt;Grid&amp;gt;
    &amp;lt;Grid.Background&amp;gt;
      &amp;lt;ImageBrush x:Name="BackgroundImageBrush"
      Stretch="UniformToFill" ImageSource="ScreenBackground.jpg" 
	  AlignmentX="Left" AlignmentY="Top"/&amp;gt;
    &amp;lt;/Grid.Background&amp;gt;
    &amp;lt;Grid.RowDefinitions&amp;gt;
      &amp;lt;RowDefinition Height="Auto"/&amp;gt;
      &amp;lt;RowDefinition Height="*"/&amp;gt;
    &amp;lt;/Grid.RowDefinitions&amp;gt;

    &amp;lt;!--TitlePanel contains the name of the application and page title--&amp;gt;
    &amp;lt;StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"&amp;gt;
      &amp;lt;TextBlock x:Name="ApplicationTitle" Text="SCREENSHOOTER" 
	  Style="{StaticResource PhoneTextNormalStyle}" 
          DoubleTap="ApplicationTitle_DoubleTap" Foreground="#FF0000" /&amp;gt;
      &amp;lt;TextBlock x:Name="PageTitle" Text="hello world" Margin="9,-7,0,0" 
	  Style="{StaticResource PhoneTextTitle1Style}" Foreground="#FF0000" /&amp;gt;
    &amp;lt;/StackPanel&amp;gt;

    &amp;lt;!--ContentPanel - place additional content here--&amp;gt;
    &amp;lt;Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"&amp;gt;
      &amp;lt;TextBlock Height="223" HorizontalAlignment="Left" Margin="52,169,0,0" 
	  Foreground="#FF0000" 
          Text="Planeth Earth is blue and there's nothing I can do" 
	  VerticalAlignment="Top" FontSize="48" TextWrapping="Wrap" /&amp;gt;
    &amp;lt;/Grid&amp;gt;
  &amp;lt;/Grid&amp;gt;
&amp;lt;/Grid&amp;gt;&lt;/pre&gt;
&lt;p&gt;A pretty basic page with all texts in bright red and a background picture; this sample uses the background of &lt;a href="http://www.windowsphone.com/en-us/apps/8b5f61a1-3ffa-df11-9264-00237de2db9e" target="_blank"&gt;Map Mania&lt;/a&gt;, about half of the globe as seen from space, but you can just use any 480x800 image. Then add just a little code to the MainPage.xaml.cs:&lt;/p&gt;&lt;pre&gt;private void ApplicationTitle_DoubleTap(object sender, GestureEventArgs e)
{
  TakeScreenShot();
}

private void TakeScreenShot()
{
  // Take a screenshot 
  var screenshot = new WriteableBitmap(this, null);
  var screenshotname = String.Format("Screenshooter_{0}", DateTime.Now.Ticks);
  using (var ms = new MemoryStream())
  {
  screenshot.SaveJpeg(ms, 480, 800, 0, 85);
  ms.Seek(0, SeekOrigin.Begin);

  var library = new MediaLibrary();
  var pic = library.SavePicture(screenshotname, ms);
  }

  MessageBox.Show(string.Concat("Screenshot saved as ", screenshotname));
}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://lh5.ggpht.com/-CThwNILC4i0/TpAjdmzueNI/AAAAAAAAG3I/3A6NybfNsxQ/s1600-h/Screenshooter_634536668888930000%25255B3%25255D.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Screenshooter_634536668888930000" border="0" alt="Screenshooter_634536668888930000" align="right" src="http://lh6.ggpht.com/-KV0UoHzicKI/TpAjeGepkVI/AAAAAAAAG3M/7TQ8vFESJQM/Screenshooter_634536668888930000_thumb%25255B1%25255D.jpg?imgmax=800" width="111" height="188"&gt;&lt;/a&gt;This is your basic screenshooter. Double-tap the header and it makes a WriteableBitmap of the entire screen, saves it as a JPEG on a MemoryStream, and writes the result into a picture in the media library. The result looks something like displayed here on the right.&lt;/p&gt;
&lt;p&gt;
&lt;p&gt;Once again this shows how simple things can be created in &lt;a href="http://www.microsoft.com/windowsphone/" target="_blank"&gt;Windows Phone 7&lt;/a&gt;. But although this application has some merits – for instance, to allow users of your App to create screenshots ‘in the field’, from a game situation or something like that – it’s pretty limited. Let’s make things a little bit more livelily and replace the static image by something more interesting – a live camera feed! &lt;/p&gt;
&lt;p&gt;This was &lt;a href="http://dotnetbyexample.blogspot.com/2011/09/mango-augmented-reality-101-showing.html" target="_blank"&gt;already described earlier in this blog&lt;/a&gt;, and applying the same technique, update the top part of the XAML a little:&lt;/p&gt;&lt;pre&gt;&amp;lt;Grid x:Name="LayoutRoot"&amp;gt;
    &amp;lt;Grid.Background&amp;gt;
      &amp;lt;VideoBrush x:Name="BackgroundVideoBrush"
          Stretch="UniformToFill" AlignmentX="Left" AlignmentY="Top"&amp;gt;
          &amp;lt;VideoBrush.Transform&amp;gt;
            &amp;lt;CompositeTransform Rotation="90" TranslateX="477"/&amp;gt;
          &amp;lt;/VideoBrush.Transform&amp;gt;
      &amp;lt;/VideoBrush&amp;gt;
    &amp;lt;/Grid.Background&amp;gt;
    &amp;lt;Grid&amp;gt;
      &amp;lt;Grid.Background&amp;gt;
        &amp;lt;ImageBrush x:Name="BackgroundImageBrush"
        Stretch="UniformToFill" Opacity="0" AlignmentX="Left" AlignmentY="Top"&amp;gt;
          &amp;lt;ImageBrush.Transform&amp;gt;
            &amp;lt;CompositeTransform Rotation="90" TranslateX="477"/&amp;gt;
          &amp;lt;/ImageBrush.Transform&amp;gt;
        &amp;lt;/ImageBrush&amp;gt;
      &amp;lt;/Grid.Background&amp;gt;&lt;/pre&gt;
&lt;p&gt;The rest of the XAML is unchanged. Notice the ImageBrush stays – its Opacity is set to 0, it’s ImageSource tag is now empty and it gets the same transform applied to as the video brush. Why it’s not simply removed will become clear in a moment. Add a little code to the MainPage.xaml.cs &lt;/p&gt;&lt;pre&gt;PhotoCamera cam;

protected override void OnNavigatedTo(NavigationEventArgs e)
{
  base.OnNavigatedTo(e);
  cam = new PhotoCamera();
  BackgroundVideoBrush.SetSource(cam);
}

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
  base.OnNavigatedFrom(e);
  cam.Dispose();
}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://lh4.ggpht.com/-d7bi8NxURqc/TpAjejr5-xI/AAAAAAAAG3Q/9dqxM9JLkJU/s1600-h/Screenshooter_634536134540840000%25255B3%25255D.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Screenshooter_634536134540840000" border="0" alt="Screenshooter_634536134540840000" align="right" src="http://lh5.ggpht.com/-n90fXuukKko/TpAjfJk4A5I/AAAAAAAAG3U/vF-hcum6bUQ/Screenshooter_634536134540840000_thumb%25255B1%25255D.jpg?imgmax=800" width="120" height="204"&gt;&lt;/a&gt;Running this app on the phone will show the live camera feed displayed as a background and the texts floating over it. Double-tap the header again, and the result is …&lt;/p&gt;
&lt;p&gt;…not what you might expect, or at least not what you had hoped. The video feed is not being captured. To get this done, a little more trickery is needed. First, add two more methods to the MainPage.xaml.cs:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;private void PrepareScreenShot()
{
  // Create capture buffer.
  var ARGBPx = new int[(int)cam.PreviewResolution.Width * 
                  (int)cam.PreviewResolution.Height];

  // Copies the current viewfinder frame into a buffer.
  cam.GetPreviewBufferArgb32(ARGBPx);

  // Copy to preview image into a writable bitmap.
  var wb = new WriteableBitmap((int)cam.PreviewResolution.Width, 
                               (int)cam.PreviewResolution.Height);
  ARGBPx.CopyTo(wb.Pixels, 0);
  wb.Invalidate();

  // Display that on the screen
  BackgroundImageBrush.ImageSource = wb;
  BackgroundImageBrush.Opacity = 1;
}

private void ContinueVideo()
{
  BackgroundImageBrush.Opacity = 0;
  BackgroundImageBrush.ImageSource = null;
}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://lh4.ggpht.com/-5PUle_4w2k0/TpAjfoBB4cI/AAAAAAAAG3Y/hm9AM9bgZmE/s1600-h/Screenshooter_634536149331290000%25255B4%25255D.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Screenshooter_634536149331290000" border="0" alt="Screenshooter_634536149331290000" align="right" src="http://lh3.ggpht.com/-ALc8IPMdX8c/TpAjgJTaW8I/AAAAAAAAG3c/bZ0vzVYrhjc/Screenshooter_634536149331290000_thumb%25255B2%25255D.jpg?imgmax=800" width="107" height="190"&gt;&lt;/a&gt;Then, add a call to “PrepareScreenShot” at the top of “TakeScreenShot”, and a call to “ContinueVideo” at the bottom of it. What this basically does is copy the viewfinder preview data into a buffer, make a WriteableBitmap of that, feed that to the as of yet transparent BackgroundImageBrush overlaying the video, and make that brush visible. Then, you have essentially a video-still beneath your texts and &lt;em&gt;that&lt;/em&gt; will get screencaptured, as showed to the right – I took a picture of my monitor showing the code of the solution. After the screenshot is saved, BackgroundImageBrush is cleared and made transparent again -and the video feed becomes visible again, ready for the next shot.&lt;/p&gt;
&lt;p&gt;One last thing to add: by this time you may have noticed that double-tapping the screen is not the best way to take a picture – they tend go get a little blurry. That’s probably another reason why Microsoft made the camera button a mandatory Windows Phone feature, so lets use it. First, add a little code for processing the camera button events:&lt;/p&gt;&lt;pre&gt;void CameraButtons_ShutterKeyHalfPressed(object sender, EventArgs e)
{
  if (cam.IsFocusSupported)
  {
    cam.Focus();
  }
}

void CameraButtons_ShutterKeyPressed(object sender, EventArgs e)
{
  TakeScreenShot();
}&lt;/pre&gt;
&lt;p&gt;This brings about another little detail: the camera can get be given a focus command, but apparently not all cameras support this, so first ask the camera if it supports focus at all. Finally, make sure the camera button events are attached &lt;em&gt;and detached&lt;/em&gt; at the right moment, so adapt the OnNavigatedTo and OnNavigatedFrom methods like this:&lt;/p&gt;&lt;pre&gt;protected override void OnNavigatedTo(NavigationEventArgs e)
{
  base.OnNavigatedTo(e);
  cam = new PhotoCamera();
  CameraButtons.ShutterKeyPressed += CameraButtons_ShutterKeyPressed;
  CameraButtons.ShutterKeyHalfPressed += CameraButtons_ShutterKeyHalfPressed;
  BackgroundVideoBrush.SetSource(cam);
}

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
  base.OnNavigatedFrom(e);
  CameraButtons.ShutterKeyPressed -= CameraButtons_ShutterKeyPressed;
  CameraButtons.ShutterKeyHalfPressed -= CameraButtons_ShutterKeyHalfPressed;
  cam.Dispose();
}&lt;/pre&gt;
&lt;p&gt;And there you have it – a basic Augmented Reality Photo shooter.&lt;/p&gt;
&lt;p&gt;All the credits go to &lt;a href="http://blogs.microsoft.nl/blogs/mhoekstra/default.aspx" target="_blank"&gt;Matthijs Hoekstra&lt;/a&gt; for laying the groundwork for this article with his &lt;a href="http://www.windowsphone.com/en-us/apps/a5d4c59b-aef6-480d-abd9-8fea04bb3c04" target="_blank"&gt;Rhino Vision&lt;/a&gt; application - and supplying me with the full sources, so I only had to &lt;strike&gt;demolish&lt;/strike&gt; refactor it into a basic understandable sample. I hope to see a boatload of ‘funny picture applications’ in the Marketplace soon.&lt;/p&gt;
&lt;p&gt;You can find the full source of the ScreenShooter sample app &lt;a href="http://www.schaikweb.net/dotnetbyexample/screenshooter.zip" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5295746446529817470-6443499404109428068?l=dotnetbyexample.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/dotnetbyexample/~4/RAaZqgrnkIo" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2012-01-16T19:53:22.704+01:00</atom:updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/-KV0UoHzicKI/TpAjeGepkVI/AAAAAAAAG3M/7TQ8vFESJQM/s72-c/Screenshooter_634536668888930000_thumb%25255B1%25255D.jpg?imgmax=800" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://dotnetbyexample.blogspot.com/2011/10/taking-screenshots-with-windows-phone-7.html</feedburner:origLink></item><item><title>Wireless podcast sync on Windows Phone 7 outside USA–yes we can!</title><link>http://feedproxy.google.com/~r/blogspot/dotnetbyexample/~3/F8Z_ybsuaXo/wireless-podcast-sync-on-windows-phone.html</link><category>WP7NL</category><category>Windows Phone 7</category><category>WP7</category><author>noreply@blogger.com (Joost van Schaik)</author><pubDate>Wed, 05 Oct 2011 12:23:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5295746446529817470.post-7777651370805075426</guid><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/VoCIJjMWrIlW1K2gdGy4KdZGLYY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/VoCIJjMWrIlW1K2gdGy4KdZGLYY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/VoCIJjMWrIlW1K2gdGy4KdZGLYY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/VoCIJjMWrIlW1K2gdGy4KdZGLYY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Sorry! No code here as well, but a usability tip.&lt;/p&gt; &lt;p&gt;Mango RTM came, the Dutch Marketplace went live, I nuked my HTC7 Pro and finally used my age-old live id as primary live id. I registered my credit card and bought my first apps. Now I knew in advance not all the cool features that were available when I still was running my fake live id based on a random ZIP code in Texas (I think) would still be there when I switched live id, but I was &lt;em&gt;not&lt;/em&gt; prepared for was the fact that the whole podcast Marketplace part was missing. Fortunately there is a work-around for this: Zune downloads anything you know the RSS for. So if you want to listen to &lt;a href="http://wpdevpodcast.com/" target="_blank"&gt;Windows Dev Podcast&lt;/a&gt; as I do every week, you just enter their RSS feed (&lt;a title="http://feeds.feedburner.com/WindowsPhoneDevPodcast" href="http://feeds.feedburner.com/WindowsPhoneDevPodcast"&gt;http://feeds.feedburner.com/WindowsPhoneDevPodcast&lt;/a&gt;) and boom, Zune starts loading their podcasts.&lt;/p&gt; &lt;p&gt;But now I was back to downloading episodes via Zune again by attaching my phone to my computer. I was just getting used to letting the phone taking care of that – as soon as it was in Wi-Fi range of my home it started to check for new episodes and lo and behold, automagically Lowdermilk &amp;amp; Lowdermilk appeared on my phone, just as the &lt;a href="http://www.dotned.nl/podcasts.aspx" target="_blank"&gt;DotNed podcast&lt;/a&gt;, &lt;a href="http://windowsteamblog.com/windows_phone/b/windowsphone/" target="_blank"&gt;Windows Phone Radio&lt;/a&gt; and more.&lt;/p&gt; &lt;p&gt;Turns out that &lt;em&gt;once you have one episode downloaded on your phone via Zune&lt;/em&gt;, you can then start synching via Wi-Fi again. It’s dead simple.&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Once you have synced a podcast episode over an USB cable via the Zune program to your phone, disconnect it  &lt;li&gt;Open Zune on your phone  &lt;li&gt;Tap “podcasts”  &lt;li&gt;Tap the&lt;em&gt; descriptive text&lt;/em&gt; of the podcast on the right, &lt;em&gt;not&lt;/em&gt; the logo  &lt;li&gt;You will get a list of downloaded episodes (default Zune downloads 3).  &lt;li&gt;And a button “subscribe”&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;And then you are where you were before you lost the podcast Marketplace. Tap it, and you are basically done. From now on your phone will sync podcast episodes over Wi-Fi again. If this is by design or by accident, I don’t know, but it works.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5295746446529817470-7777651370805075426?l=dotnetbyexample.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/dotnetbyexample/~4/F8Z_ybsuaXo" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2011-10-06T15:29:39.039+02:00</atom:updated><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total><feedburner:origLink>http://dotnetbyexample.blogspot.com/2011/10/wireless-podcast-sync-on-windows-phone.html</feedburner:origLink></item><item><title>The Standard About Page for Windows Phone 7 revisited</title><link>http://feedproxy.google.com/~r/blogspot/dotnetbyexample/~3/5aYcYmXElCY/standard-about-page-for-windows-phone-7.html</link><category>WP7NL</category><category>Windows Phone 7</category><category>MVVM Light</category><category>WP7</category><category>dotnetmag</category><author>noreply@blogger.com (Joost van Schaik)</author><pubDate>Mon, 03 Oct 2011 11:54:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5295746446529817470.post-7320860598228386832</guid><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/TDlJ8qbSc8F9Eum1f4hJlXgv6eo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/TDlJ8qbSc8F9Eum1f4hJlXgv6eo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/TDlJ8qbSc8F9Eum1f4hJlXgv6eo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/TDlJ8qbSc8F9Eum1f4hJlXgv6eo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Back to business!&lt;/p&gt; &lt;p&gt;Although section 5.6 requiring an application to have easily discoverable application name, version information, and technical support contact information is still in the &lt;a href="http://www.microsoft.com/windowsphone/" target="_blank"&gt;Windows Phone 7&lt;/a&gt;&amp;nbsp;&lt;a href="http://msdn.microsoft.com/en-us/library/hh184840(v=VS.92).aspx" target="_blank"&gt;Application Certification Requirements&lt;/a&gt;, it is no longer strictly enforced as far as I know. Yet, it’s still a very good idea to include this. It allows your App’s buyers to quickly review and rate your App and moreover, contact you easily, and usually providing you with all kinds of free ideas to make your App even better. What is better than to get direct input from the very people who bought your App!&lt;/p&gt; &lt;p&gt;I wrote about a Standard About Page &lt;a href="http://dotnetbyexample.blogspot.com/2011/01/standard-about-page-for-windows-phone-7.html" target="_blank"&gt;some time ago&lt;/a&gt;. The latest version is now included in the 2.0.1 version of my &lt;a href="http://wp7nl.codeplex.com/" target="_blank"&gt;wp7nl library on codeplex&lt;/a&gt;, which is also &lt;a href="http://www.nuget.org/List/Packages/wp7nl" target="_blank"&gt;available as a Nuget package&lt;/a&gt;. Apart from some minor improvements to the AboutViewModelBase (and the update to MVVMLight 4.0), by popular request I created a user control, or actually, multiple user controls.&lt;/p&gt; &lt;p&gt;If your reference the wp7nl library, you will get three “About” controls:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;AboutContents  &lt;li&gt;AboutData  &lt;li&gt;AboutInfoSymbol&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;AboutData is the complete thing: create an empty page, delete everything within LayoutRoot Grid, drag this control in it, bind your AboutViewModelBase descendant, and you are ready. Apart from the namespace declarations, all that’s left of the contents of the About Page of my Map Mania App now looks like this:&lt;/p&gt;&lt;pre&gt;&amp;lt;phone:PhoneApplicationPage.Resources&amp;gt;
  &amp;lt;Model:AboutViewModel x:Key="AboutViewModel"/&amp;gt;
&amp;lt;/phone:PhoneApplicationPage.Resources&amp;gt;

&amp;lt;Controls:PhoneApplicationPage.Style&amp;gt;
  &amp;lt;StaticResource ResourceKey="PhoneAppStyle"/&amp;gt;
&amp;lt;/Controls:ExtendedPhonePage.Style&amp;gt;
&amp;lt;Grid x:Name="LayoutRoot" Style="{StaticResource LayoutRootStyle}" 
   DataContext="{StaticResource AboutViewModel}"&amp;gt;
  &amp;lt;Controls:AboutData/&amp;gt;
&amp;lt;/Grid&amp;gt;&lt;/pre&gt;
&lt;p&gt;Again, by popular request this is built up out of of two sub controls, AboutContents (everthing below the actual “About”) and AboutSymbol (the info-symbol). A picture says more than a thousand words, therefore:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;a href="http://lh3.ggpht.com/-HhDSjBuogIs/TooEwXrPnJI/AAAAAAAAG0s/r5HV5clhLdw/s1600-h/About%25255B8%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="About" border="0" alt="About" src="http://lh4.ggpht.com/-fQOt2NHQxaQ/TooEw-Q6a3I/AAAAAAAAG0w/NXYodCv42Zw/About_thumb%25255B4%25255D.png?imgmax=800" width="614" height="373"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This, for instance, allowed me to construct the About ‘page’ of Catch’em Birds as part of a Panorama view, using just the AboutSymbol and the Contents like this:&lt;/p&gt;&lt;pre style="font-size: 11px"&gt;&amp;lt;controls:PanoramaItem x:Name="PanAbout" 
  Header="{Binding LocalizedResources.About, Source={StaticResource LocalizedStrings}}" 
  Margin="0,-1,0,0"&amp;gt;
  &amp;lt;controls:PanoramaItem.HeaderTemplate&amp;gt;
    &amp;lt;DataTemplate&amp;gt;
      &amp;lt;Grid&amp;gt;
        &amp;lt;Grid.RowDefinitions&amp;gt;
          &amp;lt;RowDefinition Height="0.994*"/&amp;gt;
          &amp;lt;RowDefinition Height="0.006*"/&amp;gt;
        &amp;lt;/Grid.RowDefinitions&amp;gt;
        &amp;lt;Grid.ColumnDefinitions&amp;gt;
          &amp;lt;ColumnDefinition Width="40"/&amp;gt;
          &amp;lt;ColumnDefinition Width="Auto"/&amp;gt;
        &amp;lt;/Grid.ColumnDefinitions&amp;gt;
        &amp;lt;LocalJoost:AboutInfoSymbol HorizontalAlignment="Left" 
           VerticalAlignment="Bottom" Margin="0,0,0,6"/&amp;gt;
        &amp;lt;TextBlock Grid.Column="1" 
           Text="{Binding Content, RelativeSource={RelativeSource TemplatedParent}}" 
           FontSize="64" Margin="0" Grid.RowSpan="2" /&amp;gt;
      &amp;lt;/Grid&amp;gt;
    &amp;lt;/DataTemplate&amp;gt;
  &amp;lt;/controls:PanoramaItem.HeaderTemplate&amp;gt;
  &amp;lt;LocalJoost:AboutContents Name="aboutContents1" 
    DataContext="{Binding Instance.AboutViewModel, Source={StaticResource MainViewModel}}" /&amp;gt;
&amp;lt;/controls:PanoramaItem&amp;gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://lh5.ggpht.com/-wl6tuWdLcK0/TooExSOpBMI/AAAAAAAAG00/CiajgVDHXIY/s1600-h/about2%25255B2%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px 8px 0px 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="about2" border="0" alt="about2" align="left" src="http://lh3.ggpht.com/-hI6ca6uxkAQ/TooEx0TdsoI/AAAAAAAAG04/ONxujnWVR1A/about2_thumb.png?imgmax=800" width="148" height="244"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Which yields the result as displayed on the left. &lt;/p&gt;
&lt;p&gt;So now you can create an About Page with even less effort. You still have to make a child class of AboutViewModelBase and a resource file as described in &lt;a href="http://dotnetbyexample.blogspot.com/2011/01/standard-about-page-for-windows-phone-7.html" target="_blank"&gt;the first About Page post&lt;/a&gt; but that’s about all. &lt;/p&gt;
&lt;p&gt;A sample implementation of the whole stuff can be found &lt;a href="www.schaikweb.net/dotnetbyexample/demoabout.zip" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Have fun!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5295746446529817470-7320860598228386832?l=dotnetbyexample.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/dotnetbyexample/~4/5aYcYmXElCY" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2011-12-03T16:22:54.900+01:00</atom:updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/-fQOt2NHQxaQ/TooEw-Q6a3I/AAAAAAAAG0w/NXYodCv42Zw/s72-c/About_thumb%25255B4%25255D.png?imgmax=800" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total><feedburner:origLink>http://dotnetbyexample.blogspot.com/2011/10/standard-about-page-for-windows-phone-7.html</feedburner:origLink></item><item><title>Being spammed to MVP</title><link>http://feedproxy.google.com/~r/blogspot/dotnetbyexample/~3/Xvb7DH9TBLg/being-spammed-to-mvp.html</link><category>Off-topic</category><category>Windows Phone 7</category><author>noreply@blogger.com (Joost van Schaik)</author><pubDate>Sun, 02 Oct 2011 03:27:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5295746446529817470.post-2815295046538179886</guid><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/CVR5tOcZOi-Vx6mQ3c83iHBno2g/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CVR5tOcZOi-Vx6mQ3c83iHBno2g/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/CVR5tOcZOi-Vx6mQ3c83iHBno2g/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CVR5tOcZOi-Vx6mQ3c83iHBno2g/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;This posting is not about code or anything. Skip it if you are searching for that ;)&lt;/p&gt; &lt;p&gt;I had a rotten day yesterday. I was tired from an extremely busy and stressed-out working week, I slept badly, and I was developing a severe cold while it finally looked like nice weather here. I was visiting my mum – who was relating about the funeral of my niece the day before. She had passed away out of the blue at 46, just four years older than me. This made me ponder about my own future, my dad who passed away at 48 (when I was only 15), stuff like that. A cheerful mood indeed.&lt;/p&gt; &lt;p&gt;In the godforsaken town my mum lives there’s hardly wireless internet, so I saw two or three MVP renewals trickling in, but could hardly respond. Nor was I really in the mood for it. Next stop were my parents-in-law, who live in the same town a couple of blocks away (yeah so I married the Girl Next Door, sue me ;) ) for a family BBQ. Fortunately no sick or dead relatives talk here, but to compensate for that I had developed a splitting headache. Picture the scene? “One of those days”.&lt;/p&gt; &lt;p&gt;So while I was listlessly munching away some BBQ stuff I wanted to show my &lt;a href="http://www.microsoft.com/windowsphone/" target="_blank"&gt;Windows Phone 7&lt;/a&gt; to my Android-using brother in law (his Facebook App was broken again) and for some reason noticed a revolving live tile with a twitter message congratulating new and renewed MVP’s in general and if everyone else could please check their spam folder? So I connected to my father-in-laws Wi-Fi network (he’s a bit more up-to-date than my mum), and still not believing anything I let my phone sync my gmail spam folder and picked it up again 10 minutes later or so.&lt;/p&gt; &lt;p&gt;I almost dropped my phone and I suppose I made some kind of strangled sound. I don’t quite remember, I think a few neurons fused out that moment ;) - just that my wife looked at me with that special worried ‘what the hell is wrong with YOU?’ look. I just showed her my phone. It read: &lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;strong&gt;&lt;em&gt;Congratulations 2011 Microsoft MVP!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;Congratulations! We are pleased to present you with the 2011 Microsoft® MVP Award! This award is given to exceptional technical community leaders who actively share their high quality, real world expertise with others. We appreciate your outstanding contributions in Windows Phone Development technical communities during the past year.&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;She passed it to the people present and they all started to congratulate me. &lt;em&gt;Still&lt;/em&gt; not believing it, I managed to retrieve my phone and contacted our local Windows Phone 7 DPE &lt;a href="http://blogs.microsoft.nl/blogs/mhoekstra/default.aspx" target="_blank"&gt;Matthijs Hoekstra&lt;/a&gt; (using – how fitting – Windows Phone 7 Live Messenger integration, or maybe Facebook chat, I did not quite pay attention to that) to check if no-one was pulling a sick joke on me. He confirmed it was the real thing and he was already wondering why he did not hear anything from me – it was more than 2.5 hours since the mails got out.&lt;/p&gt; &lt;p&gt;I can assure you even Windows Phone 7 auto correction had a hard time with my trembling hands (sneezing in the process does not help either), but I finally managed to get out&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-mdvcwP9L958/ToibiRMXq4I/AAAAAAAAG0k/dDqpqgGJNv8/s1600-h/twitter%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="twitter" border="0" alt="twitter" src="http://lh3.ggpht.com/-LQ4DB7MPlWU/Tog8oWRZ19I/AAAAAAAAG0o/fLKeKga6TZA/twitter_thumb%25255B3%25255D.png?imgmax=800" width="509" height="105"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;… and then my phone nearly exploded with congratulations, it was just impossible to keep up with it and thank everyone in person. It’s a bit lame, but hereby: thank you all for your good wishes and congratulations. I especially thank my fellow developers from &lt;a href="http://twitter.com/#!/search/%23wp7nl" target="_blank"&gt;#wp7nl&lt;/a&gt; who have nominated me. I hope to prove being worthy of this honor.&lt;/p&gt; &lt;p&gt;Just remember this: I will not deny being very proud of this, but I am still &lt;em&gt;just Joost&lt;/em&gt;. I am an ordinary developer just like you, who got enthusiastic about Windows Phone 7. I like to tinker, code, write (and write about code), help out other people who got stuck if I can, share ideas and knowledge, on a user or developer level. Just because I have fun doing that, and I learn a lot in the process of doing so, too. Apparently I did this in a way that pleased some people within Microsoft to such an extent that they decided to praise me in public this way. I appreciate this very much, but I never was, nor will I ever be, a divine oracle of Windows Phone 7. Nor have I transcended to some god-like being.&lt;/p&gt; &lt;p&gt;So please don’t approach me differently because ‘wow he’s now an MVP’ right? Still ‘just Joost’, who will help if he can.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5295746446529817470-2815295046538179886?l=dotnetbyexample.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/dotnetbyexample/~4/Xvb7DH9TBLg" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2011-10-02T19:51:00.581+02:00</atom:updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/-LQ4DB7MPlWU/Tog8oWRZ19I/AAAAAAAAG0o/fLKeKga6TZA/s72-c/twitter_thumb%25255B3%25255D.png?imgmax=800" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total><feedburner:origLink>http://dotnetbyexample.blogspot.com/2011/10/being-spammed-to-mvp.html</feedburner:origLink></item><item><title>Mango ‘Augmented Reality’ 101: showing a video background</title><link>http://feedproxy.google.com/~r/blogspot/dotnetbyexample/~3/0LsMzpjNMoY/mango-augmented-reality-101-showing.html</link><category>Mango</category><category>WP7NL</category><category>Windows Phone 7</category><category>Augmented Reality</category><category>wpdev</category><category>WP7</category><category>dotnetmag</category><author>noreply@blogger.com (Joost van Schaik)</author><pubDate>Mon, 26 Sep 2011 11:44:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5295746446529817470.post-3814849185327305492</guid><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/puHJ2Xv3mw1zlWE99oeLkhdNLcU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/puHJ2Xv3mw1zlWE99oeLkhdNLcU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/puHJ2Xv3mw1zlWE99oeLkhdNLcU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/puHJ2Xv3mw1zlWE99oeLkhdNLcU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Some things on Windows Phone 7.5 “Mango” are so easy that it’s almost embarrassing. Like showing a running video of what the camera is seeing on the background. So simple, in fact, that no-one ventures to describe it. And consequently, you might spend some fruitless time looking for it. I am therefore very thankful to &lt;a href="http://blogs.microsoft.nl/blogs/mhoekstra/default.aspx" target="_blank"&gt;Matthijs Hoekstra&lt;/a&gt; for sending me a piece of sample code that I condensed even more.&lt;/p&gt; &lt;p&gt;First, you need to make a new Windows Phone application for framework 7.1. In the MainPage.xaml, delete everything between the phone:PhoneApplicationPage, i.e. the complete grid “LayoutRoot”&lt;/p&gt; &lt;p&gt;Then, set &lt;strong&gt;SupportedOrientations&lt;/strong&gt; and &lt;strong&gt;Orientation&lt;/strong&gt; to "Portrait" and&amp;nbsp; &lt;strong&gt;shell:SystemTray.IsVisible&lt;/strong&gt; to “False”&lt;/p&gt; &lt;p&gt;Then you add the following XAML code:&lt;/p&gt;&lt;pre&gt;&amp;lt;Rectangle &amp;gt;
  &amp;lt;Rectangle.Fill&amp;gt;
    &amp;lt;VideoBrush x:Name="videoBrush" /&amp;gt;
  &amp;lt;/Rectangle.Fill&amp;gt;
&amp;lt;/Rectangle&amp;gt;&lt;/pre&gt;
&lt;p&gt;And then you make sure the following code is in the MainPage.xaml.cs:&lt;/p&gt;&lt;pre&gt;public MainPage()
{
  InitializeComponent();
  Loaded += MainPage_Loaded;
}

void MainPage_Loaded(object sender, RoutedEventArgs e)
{
  var cam = new PhotoCamera();
  videoBrush.SetSource(cam);
}&lt;/pre&gt;
&lt;p&gt;Deploy the app, and you will see the camera view on your screen. See what I mean by “embarrassingly simple”? Now do something funny with it ;-)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5295746446529817470-3814849185327305492?l=dotnetbyexample.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/dotnetbyexample/~4/0LsMzpjNMoY" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2011-10-08T12:20:56.184+02:00</atom:updated><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total><feedburner:origLink>http://dotnetbyexample.blogspot.com/2011/09/mango-augmented-reality-101-showing.html</feedburner:origLink></item><item><title>New binding possibilities in Mango</title><link>http://feedproxy.google.com/~r/blogspot/dotnetbyexample/~3/IwiJ8Wa9PLY/new-binding-possibilities-in-mango.html</link><category>behavior</category><category>Mango</category><category>WP7NL</category><category>XAML</category><category>Windows Phone 7</category><category>MVVM Light</category><category>WP7</category><category>DataBinding</category><category>dotnetmag</category><author>noreply@blogger.com (Joost van Schaik)</author><pubDate>Fri, 12 Aug 2011 08:18:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5295746446529817470.post-7253678190577467646</guid><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/M8ikHar269s1P8jtmRvXiws8szY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/M8ikHar269s1P8jtmRvXiws8szY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/M8ikHar269s1P8jtmRvXiws8szY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/M8ikHar269s1P8jtmRvXiws8szY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Apart from all the goodness the new API’s in “Mango” bring us, there is that other great gift that it brings us: Silverlight 4. After spending so much time on &lt;a href="http://www.microsoft.com/windowsphone/en-us/default.aspx" target="_blank"&gt;Windows Phone 7&lt;/a&gt; you would almost forget that there’s life after the ‘Silverlight 3+’ version that was the baseline up till now. This means for &lt;a href="http://mvvmlight.codeplex.com/" target="_blank"&gt;MVVMLight&lt;/a&gt; fans like me:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;You can now directly bind a command to a button’s “Command” property. In fact, you can bind a command to &lt;em&gt;anything&lt;/em&gt; that derives from ButtonBase. This includes HyperlinkButton, RadioButton, and CheckBox (and possibly more). If you bind commands to these user interface elements, you can now say goodbye to your good old friends EventTrigger and EventToCommand &lt;/li&gt;    &lt;li&gt;If you want to use data from your model in a &lt;em&gt;behavior&lt;/em&gt;, you can now bind directly bind data &lt;em&gt;to dependency properties defined in the behavior itself&lt;/em&gt;, in stead of doing the attached dependency property dance, or resorting to the MVVMLight Messenger. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The first one saves a bucket load of XAML. Before Mango, you had to create something like this to fire a command by a button being clicked:&lt;/p&gt;  &lt;pre style="font-size: 12px"&gt;&amp;lt;Button Content=&amp;quot;Start game&amp;quot;&amp;gt;
  &amp;lt;Interactivity:Interaction.Triggers&amp;gt;
    &amp;lt;Interactivity:EventTrigger EventName=&amp;quot;Click&amp;quot;&amp;gt;
      &amp;lt;MvvmLight_Command:EventToCommand Command=&amp;quot;{Binding StartNewGame, Mode=OneWay}&amp;quot;/&amp;gt;
    &amp;lt;/Interactivity:EventTrigger&amp;gt;
  &amp;lt;/Interactivity:Interaction.Triggers&amp;gt;
&amp;lt;/Button&amp;gt;&lt;/pre&gt;

&lt;p&gt;Now you can write the same functionality like this:&lt;/p&gt;

&lt;pre style="font-size: 12px"&gt;&amp;lt;Button Content=&amp;quot;Start game&amp;quot; Command=&amp;quot;{Binding StartNewGame, Mode=OneWay}&amp;quot;/&amp;gt;&lt;/pre&gt;

&lt;p&gt;By no means this means the end of EventToCommand. First of all, it needs to be there for backward compatibility (unless you particularly like rewriting working XAML) .Second, there are plenty of cases for user interface elements that generate particular events that you might want to route to a model via a command. For example, I routinely signal my model a page has completed loading by attaching a command to it’s “Loaded” event. That still requires the EventTrigger-EventToCommand route. &lt;/p&gt;

&lt;p&gt;For behaviors, the gain is a little bit less visible. But remember &lt;a href="http://dotnetbyexample.blogspot.com/2011/03/simple-windows-phone-7-silverlight.html" target="_blank"&gt;my little Windows Phone Drag/Flick behavior&lt;/a&gt;? That sports a dependency property BrakeSpeed that I could now bind to my ViewModel on all instances, thereby controlling all behaviors’ brake speed with one property. The same goes for my &lt;a href="http://dotnetbyexample.blogspot.com/2011/04/preventing-objects-made-invisible-by.html" target="_blank"&gt;SetInitialOpacityBehavior&lt;/a&gt;, where I explicitly state that you cannot bind to its OpacityAfterLoading property:&amp;#160; “in Windows Phone 7 you cannot data bind it because it’s currently based on Silverlight 3 which only allow you to bind to classes that do descend from DependencyObject – which a behavior obviously does not ;-)”. Well, now you can, and this gives you a powerful and easy way to control behaviors from your ViewModel, and let behaviors push data back to it.&lt;/p&gt;

&lt;p&gt;All in all, the ‘Silverlight4+’ in Windows Phone 7 “Mango”&amp;#160; gives us all the opportunities to make MVVMLight based applications even more easy and clean than they already were.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5295746446529817470-7253678190577467646?l=dotnetbyexample.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/dotnetbyexample/~4/IwiJ8Wa9PLY" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2011-08-12T22:32:44.843+02:00</atom:updated><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://dotnetbyexample.blogspot.com/2011/08/new-binding-possibilities-in-mango.html</feedburner:origLink></item><item><title>MVVMLight based language selection for Windows Phone 7</title><link>http://feedproxy.google.com/~r/blogspot/dotnetbyexample/~3/rpWuD-I7S0c/mvvmlight-based-language-selection-for.html</link><category>MVVM</category><category>WP7NL</category><category>Windows Phone 7</category><category>MVVM Light</category><category>WP7</category><category>Windows Mobile</category><category>dotnetmag</category><author>noreply@blogger.com (Joost van Schaik)</author><pubDate>Sun, 24 Jul 2011 04:58:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5295746446529817470.post-706594134394839137</guid><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/GILGXsWTpMuRlfu1mGnzB9zLLZw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/GILGXsWTpMuRlfu1mGnzB9zLLZw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/GILGXsWTpMuRlfu1mGnzB9zLLZw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/GILGXsWTpMuRlfu1mGnzB9zLLZw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;span style="font-style:italic;"&gt;Updated 25-09-2011 with a new implementation of LanguageSettingsViewModel to make it compatible with SilverlightSerializer. It appeared that every 2nd tombstoning of this viewmodel it lost it’s CurrentLanguage property&lt;/span&gt;
&lt;p&gt;With the advent of the ‘Mango’ release of &lt;a href="http://www.microsoft.com/windowsphone/en-us/default.aspx" target="_blank"&gt;Windows Phone 7&lt;/a&gt; with 19 more countries getting a Marketplace, supporting more than your own native language or English becomes all the more important. I can tell from personal experience that for instance supporting German gives a tremendous boost to your downloads. Tremendous as in: I get almost as much downloads from Germany as from the whole USA. Apparently Windows Phone 7 is doing pretty well in Germany. So take note of this ‘Geheimtipp’ ;-)&lt;/p&gt; &lt;p&gt;I implemented the following solution, based on &lt;a href="http://mvvmlight.codeplex.com/" target="_blank"&gt;MVVMLight&lt;/a&gt; 4, which upon first startup automatically tries to select a language based upon the current UI locale, and if that fails, tries to select one from the same group (for instance, if I only have en-UK it tries to select the first language that starts with “en”, for instance en-US). And of course you give the possibility of selecting another language manually.&lt;/p&gt; &lt;p&gt;It works like this. First, I define a very simple class that describes the base properties of a language, i.e. the locale (for instance en-US) and the way you want this language described:&lt;/p&gt;&lt;pre style="font-size: 11px"&gt;using System;
using GalaSoft.MvvmLight;

namespace Wp7nl.Globalization
{
  /// &amp;lt;summary&amp;gt;
  /// Supported languages
  /// &amp;lt;/summary&amp;gt;
  public class Language : ViewModelBase, IEquatable&amp;lt;Language&amp;gt;
  {
    private string locale;
    public string Locale
    {
      get { return locale; }
      set
      {
        if (locale != value)
        {
          locale = value;
          RaisePropertyChanged(() =&amp;gt; Locale);
        }
      }
    }

    private string description;
    public string Description
    {
      get { return description; }
      set
      {
        if (description != value)
        {
          description = value;
          RaisePropertyChanged(() =&amp;gt; Description);
        }
      }
    }

    public override string ToString()
    {
      return Description;
    }

    public bool Equals(Language other)
    {
      return other != null &amp;amp;&amp;amp; other.Locale.Equals(Locale);
    }

    public override bool Equals(object obj)
    {
      return Equals(obj as Language);
    }

    public override int GetHashCode()
    {
      return Locale.GetHashCode();
    }
  }
}&lt;/pre&gt;
&lt;p&gt;I may look like a lot but it’s only two properties and an implementation of Equals. I implemented it as a full view model, which is actually a bit overkill, but I tend to do this since I have a couple of code snippets that make this pretty easy anyway. The second class does actually all the work:&lt;/p&gt;&lt;pre style="font-size: 11px"&gt;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Threading;
using GalaSoft.MvvmLight;

namespace Wp7nl.Globalization
{
  /// &amp;lt;summary&amp;gt;
  /// A ViewModel class to handle language settings. 
  /// Override this class and add languages in the constructor
  /// &amp;lt;/summary&amp;gt;
  public class LanguageSettingsViewModel : ViewModelBase
  {
    public LanguageSettingsViewModel()
    {
      AddLanguages(new Language { Description = "English", Locale = "en-US" });
    }

    private readonly ObservableCollection&amp;lt;Language&amp;gt; supportedLanguages =
       new ObservableCollection&amp;lt;Language&amp;gt;();

    /// &amp;lt;summary&amp;gt;
    /// Gets the supported languages.
    /// &amp;lt;/summary&amp;gt;
    public ObservableCollection&amp;lt;Language&amp;gt; SupportedLanguages
    {
      get { return supportedLanguages; }
    }

    /// &amp;lt;summary&amp;gt;
    /// Determine current language
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
    private Language GetDefaultLanguage()
    {
      // Try to select from current UI thread on full name
      var language = SupportedLanguages.Where(
        p =&amp;gt; p.Locale == Thread.CurrentThread.CurrentUICulture.Name).FirstOrDefault();
      if (language == null)
      {
        // Try to select from current UI thread on 2 letter ISO code
        language =
          SupportedLanguages.Where(
            p =&amp;gt; p.Locale.StartsWith(
              Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName)).First();
      }
      if (language == null)
      {
        // Still no language: take the first one that starts with English
        language = SupportedLanguages.Where(p =&amp;gt; p.Locale.Contains("en")).First();
      }

      return language;
    }

    private Language currentLanguage;
    /// &amp;lt;summary&amp;gt;
    /// Gets or sets the current language.
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;value&amp;gt;
    /// The current language.
    /// &amp;lt;/value&amp;gt;
    public Language CurrentLanguage
    {
      get
      {
        return currentLanguage;
      }
      set
      {
        if (currentLanguage != value)
        {
          currentLanguage = value;
          RaisePropertyChanged(() =&amp;gt; CurrentLanguage);
        }
      }
    }


    /// &amp;lt;summary&amp;gt;
    /// Sets the language from current locale.
    /// &amp;lt;/summary&amp;gt;
    public void SetLanguageFromCurrentLocale()
    {
      string locale = 
        CurrentLanguage == null ? GetDefaultLanguage().Locale : CurrentLanguage.Locale;
      Thread.CurrentThread.CurrentUICulture = new CultureInfo(locale);
      Thread.CurrentThread.CurrentCulture = new CultureInfo(locale);
    }

    /// &amp;lt;summary&amp;gt;
    /// Adds the languages.
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;param name="languages"&amp;gt;The languages.&amp;lt;/param&amp;gt;
    public void AddLanguages(params Language[] languages)
    {
      if (languages != null &amp;&amp; languages.Count() &amp;gt; 0)
      {
        foreach (var l in languages)
        {
          if (!supportedLanguages.Contains(l))
          {
            supportedLanguages.Add(l);
          }
        }
      }
    }
  }
}&lt;/pre&gt;
&lt;p&gt;Out of the box this thing only supports English-USA. To add more languages, you subclass this model and add your own languages:&lt;/p&gt;&lt;pre style="font-size: 12px"&gt;using Wp7nl.Globalization;

namespace YourApp.ViewModels
{
  public class MyLanguagesViewModel : LanguageSettingsViewModel
  {
    public LanguageViewModel()
    {
       AddLanguages(new Language { Description = "Nederlands", Locale = "nl-NL" });
       AddLanguages(new Language { Description = "Deutsch", Locale = "de-DE" });
    }
  }
}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://lh5.ggpht.com/-izp4qcsZrJw/TiwI_LFgWoI/AAAAAAAAGp0/ApBpj7ei_40/s1600-h/screenshot_7-24-2011_13.44.6.244%25255B5%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="screenshot_7-24-2011_13.44.6.244" border="0" alt="screenshot_7-24-2011_13.44.6.244" align="right" src="http://lh4.ggpht.com/-oYk2yh1mi3w/TiwI_2q84VI/AAAAAAAAGp4/Fu1Rf5XPPpE/screenshot_7-24-2011_13.44.6.244_thumb%25255B3%25255D.png?imgmax=800" width="200" height="392"&gt;&lt;/a&gt;Directly after you have created MyLanguagesViewModel, or retrieved it from tombstoning &lt;a href="http://dotnetbyexample.blogspot.com/2011/01/tombstoning-mvvmlight-viewmodels-with.html" target="_blank"&gt;using my extension methods based upon SilverlightSerializer&lt;/a&gt;, you simply call the SetLanguageFromCurrentLocale and that either restores the selection last made by the user in the application itself, or tries to find the language that best fits what the user has selected as locale on his phone. To give the user an option to select a language you can, for instance, bind the models’ SupportedLanguages property to the ItemsSource property of a &lt;a href="http://blogs.msdn.com/b/delay/archive/2010/11/03/listpicker-i-hardly-even-know-er-a-detailed-overview-of-the-windows-phone-toolkit-s-listpicker-control.aspx" target="_blank"&gt;ListPicker&lt;/a&gt; and the CurrentLanguage to its SelectedItems property.&lt;/p&gt;
&lt;p&gt;In my as of yet unreleased Mango version of Map Mania this looks like as displayed on the right:&lt;/p&gt;
&lt;p&gt;This leaves, of course, still two things to do:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Defining resources files with with the actual text 
&lt;li&gt;Implement a class that makes these resource files bindable &lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;This procedure is shown in the &lt;a href="http://go.microsoft.com/fwlink/?LinkId=190350" target="_blank"&gt;Windows Phone 7 Globalization Sample&lt;/a&gt; provided on &lt;a href="http://msdn.microsoft.com/en-us/library/ff431744(v=vs.92).aspx" target="_blank"&gt;MSDN&lt;/a&gt; so I won’t repeat them here.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5295746446529817470-706594134394839137?l=dotnetbyexample.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/dotnetbyexample/~4/rpWuD-I7S0c" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2011-10-19T19:32:11.853+02:00</atom:updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/-oYk2yh1mi3w/TiwI_2q84VI/AAAAAAAAGp4/Fu1Rf5XPPpE/s72-c/screenshot_7-24-2011_13.44.6.244_thumb%25255B3%25255D.png?imgmax=800" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://dotnetbyexample.blogspot.com/2011/07/mvvmlight-based-language-selection-for.html</feedburner:origLink></item><item><title>Speed and distance calculation extension methods for Windows Phone 7</title><link>http://feedproxy.google.com/~r/blogspot/dotnetbyexample/~3/V_4T4x1cX74/speed-and-distance-calculation.html</link><category>WP7NL</category><category>Windows Phone 7</category><category>WP7</category><category>dotnetmag</category><author>noreply@blogger.com (Joost van Schaik)</author><pubDate>Sat, 23 Jul 2011 06:31:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5295746446529817470.post-6494776012143912591</guid><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ZDGOHxSz55daJms_JDZqjZGj1is/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ZDGOHxSz55daJms_JDZqjZGj1is/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ZDGOHxSz55daJms_JDZqjZGj1is/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ZDGOHxSz55daJms_JDZqjZGj1is/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Upgrading stuff to from &lt;a href="http://www.microsoft.com/windowsphone/en-us/default.aspx" target="_blank"&gt;Windows Phone 7&lt;/a&gt; to “Mango” is sometimes like cleaning your desk drawer before going on a holiday – you stumble upon stuff you forgot it was even there. For the ‘game engine’ I made for Catch’em Birds I created a few very handy extension methods for calculating speed and distance, which I would like to share with the rest of the community:&lt;/p&gt;  &lt;pre&gt;using System;
#if WINDOWS_PHONE
using System.Windows;
#else
using System.Drawing;
using System.Windows;
#endif


namespace Wp7nl.Utilities
{
  public static class PointExtensions
  {
    /// &amp;lt;summary&amp;gt;
    /// Distances from point 1 to point 2
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;param name=&amp;quot;p1&amp;quot;&amp;gt;The first point.&amp;lt;/param&amp;gt;
    /// &amp;lt;param name=&amp;quot;p2&amp;quot;&amp;gt;The second point.&amp;lt;/param&amp;gt;
    /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
    public static double DistanceFrom(this Point p1, Point p2)
    {
      var dX = p2.X - p1.X;
      var dY = p2.Y - p1.Y;
      return Math.Sqrt(dX * dX + dY * dY);
    }

    /// &amp;lt;summary&amp;gt;
    /// Calculates the speed in pixels per second
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;param name=&amp;quot;p1&amp;quot;&amp;gt;The first point.&amp;lt;/param&amp;gt;
    /// &amp;lt;param name=&amp;quot;p2&amp;quot;&amp;gt;The second point.&amp;lt;/param&amp;gt;
    /// &amp;lt;param name=&amp;quot;duration&amp;quot;&amp;gt;The duration&amp;lt;/param&amp;gt;
    /// &amp;lt;returns&amp;gt;Speed in pixels per second&amp;lt;/returns&amp;gt;
    public static double CalculateSpeed(this Point p1, Point p2, Duration duration)
    {
      return p1.DistanceFrom(p2) / duration.TimeSpan.TotalSeconds;
    }

    /// &amp;lt;summary&amp;gt;
    /// Calculates the duration given a distance and a speed.
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;param name=&amp;quot;p1&amp;quot;&amp;gt;The first point.&amp;lt;/param&amp;gt;
    /// &amp;lt;param name=&amp;quot;p2&amp;quot;&amp;gt;The second point.&amp;lt;/param&amp;gt;
    /// &amp;lt;param name=&amp;quot;speed&amp;quot;&amp;gt;The speed in pixels per second.&amp;lt;/param&amp;gt;
    /// &amp;lt;returns&amp;gt;Time it takes to get from p1 to p2&amp;lt;/returns&amp;gt;
    public static Duration CalculateDuration(this Point p1, Point p2, double speed)
    {
      return new Duration(TimeSpan.FromSeconds(p1.DistanceFrom(p2) / speed));
    }
  }
}&lt;/pre&gt;

&lt;p&gt;I will discuss these in a not quite logical order:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The first method is of course good ole' Pythagoras caught in an extension method, basically there as a helper method for the other two. &lt;/li&gt;

  &lt;li&gt;The third method is the one I used most: given that my object needs to move from p1 to p2 with a given speed in pixels per second, what’s the Duration I need to apply to my Storyboard? &lt;/li&gt;

  &lt;li&gt;The second one is the inverse – given the fact that on object was moving from p1 to p2 in duration “duration”, calculate its speed in pixels per second. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see at the #if on top it also work on System.Drawing.Points under full .NET 4.0. Maybe these methods are useful there as well, I put that only there to facilitate some unit tests.&lt;/p&gt;

&lt;p&gt;All these methods are part of the &lt;a href="http://wp7nl.codeplex.com/" target="_blank"&gt;wp7nl CodePlex library&lt;/a&gt; – or at least the will so at the upcoming Mango release.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update: thanks to &lt;a href="http://twitter.com/#!/rschu" target="_blank"&gt;Rene Schulte&lt;/a&gt; for pointing out to me that my original DistanceFrom method using Math.Pow is very slow compared to simple multiplications. Rene is a Silverlight MVP from Dresden, Germany and has &lt;a href="http://kodierer.blogspot.com/2010/08/rect-and-point-extension-methods.html" target="_blank"&gt;some very nice Point extension methods on his blog “Kodierer”&lt;/a&gt; as well - in English, don’t worry ;-)&lt;/em&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5295746446529817470-6494776012143912591?l=dotnetbyexample.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/dotnetbyexample/~4/V_4T4x1cX74" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2011-08-12T17:33:28.575+02:00</atom:updated><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://dotnetbyexample.blogspot.com/2011/07/speed-and-distance-calculation.html</feedburner:origLink></item><item><title>Concatenating a long set of objects in a string with a separator</title><link>http://feedproxy.google.com/~r/blogspot/dotnetbyexample/~3/WFdhgUwogDs/concatenating-long-set-of-objects-in.html</link><category>C#</category><category>string</category><author>noreply@blogger.com (Joost van Schaik)</author><pubDate>Wed, 20 Jul 2011 08:56:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5295746446529817470.post-7432244046226152527</guid><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Jt4yO0wvyDH3qg7BVjtcQnprsfY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Jt4yO0wvyDH3qg7BVjtcQnprsfY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Jt4yO0wvyDH3qg7BVjtcQnprsfY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Jt4yO0wvyDH3qg7BVjtcQnprsfY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;It still amazes me when I see people concatenating a long set of repetitive strings with a StringBuilder, adding a separator to each string it, and then remove the last separator – or doing some complex if-statement comparing a count or index to prevent a trailing separator or something. &lt;/p&gt;  &lt;p&gt;This is a very simple trick I use a lot of times when I need, for instance, to change a list of points into it’s &lt;a href="http://en.wikipedia.org/wiki/Well-known_text" target="_blank"&gt;Well Known Text (WKT)&lt;/a&gt; representation. So let’s assume we have a variable &lt;em&gt;points&lt;/em&gt; of IList&amp;lt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.point.aspx" target="_blank"&gt;System.Windows.Point&lt;/a&gt;&amp;gt;, that I want to convert to a list of coordinates that fit in WKT string. That is: X and Y separated by a space, and coordinates separated by a comma. I can do that with this simple statement that would have been a one-liner if it had not been for lack of space ;-) :&lt;/p&gt;  &lt;pre&gt;var pointString = 
  string.Join(&amp;quot;, &amp;quot;,
    points.Select(p =&amp;gt; 
      string.Format(CultureInfo.InvariantCulture, &amp;quot;{0} {1}&amp;quot;, p.X, p.Y)));&lt;/pre&gt;

&lt;p&gt;If I had points X=10, Y=15, X=20, Y=25 and X=30 ,Y=40 this would nicely translate to&lt;/p&gt;

&lt;p&gt;&lt;font face="Courier New"&gt;10 15,20 25,30 40&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;That's all. No loops, no truncating trailing comma’s: just a Select and a Join&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5295746446529817470-7432244046226152527?l=dotnetbyexample.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/dotnetbyexample/~4/WFdhgUwogDs" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2011-07-20T19:58:05.713+02:00</atom:updated><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://dotnetbyexample.blogspot.com/2011/07/concatenating-long-set-of-objects-in.html</feedburner:origLink></item><item><title>Using Kinect and MVVMLight 4 for some basic Google Maps manipulation</title><link>http://feedproxy.google.com/~r/blogspot/dotnetbyexample/~3/c2w2JARZ94s/using-kinect-and-mvvmlight-4-for-some.html</link><category>MVVM</category><category>WPF</category><category>NUI</category><category>Kinect</category><category>XAML</category><category>Natural User Interfaces</category><category>MVVM Light</category><category>dotnetmag</category><author>noreply@blogger.com (Joost van Schaik)</author><pubDate>Sat, 16 Jul 2011 04:50:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5295746446529817470.post-3155896843536668226</guid><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ocZOGLxAFZa8NPUhPSA7QOwyaZ4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ocZOGLxAFZa8NPUhPSA7QOwyaZ4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ocZOGLxAFZa8NPUhPSA7QOwyaZ4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ocZOGLxAFZa8NPUhPSA7QOwyaZ4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Being a new tech junkie, I of course wanted to try the waters when the &lt;a href="http://research.microsoft.com/en-us/um/redmond/projects/kinectsdk/" target="_blank"&gt;Kinect beta SDK&lt;/a&gt; was released on June 16, 2011. I thought it best to avoid domestic trouble and let the Kinect my wife bought back in December sit nicely connected to the XBox360 downstairs, and ordered a second Kinect – which just happened to be on sale for only €99.&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;The global idea&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;I wanted to create a simple application that allows you to both pan and zoom on a standard Google Maps web site, using hand gestures and some speech commands. I wanted to show visual feedback projected over the browser, like moving hands and stuff like that. Because I wanted to re-use some of my hard-won &lt;a href="http://www.microsoft.com/windowsphone/en-us/default.aspx" target="_blank"&gt;Windows Phone 7&lt;/a&gt; knowledge, I wanted to use MVVM as well. So enter &lt;a href="http://mvvmlight.codeplex.com/" target="_blank"&gt;MVVMLight&lt;/a&gt; and while I was at it, version 4 too. The SDK is not usable from Silverlight, so the choice fell logically on Windows Presentation Foundation (WPF) to host a browser and see how things went from there. The result is below. It’s pretty crude and the user experience leaves much to be desired, but it’s a nice start. I will explain what I’ve done and why, and as usual include the &lt;a href="http://www.schaikweb.net/dotnetbyexample/mapcontroller.zip" target="_blank"&gt;whole sample application&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;Basic operation&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;When the application opens up, it shows Google Maps in a full screen browser, and pretty much nothing else. To enable a demo I am planning to give, the Kinect is not immediately initialized. Forgive this old Trekkie - I could not resist. For years I’ve envied Kirk and Picard for being able to command their computer by talking to it. To get the application to start tracking your hands, you have to say “&lt;em&gt;Kinect engage&lt;/em&gt;”. :-)&lt;/p&gt;  &lt;p&gt;If Kinect understands your command, it will show the command to the left. If you move your hands, to yellow semi-transparent hand symbols should appear. If you move your hands from left to right they follow you – moving them forward will make them smaller, moving them backward bigger.&lt;/p&gt;  &lt;p&gt;If you say “&lt;em&gt;Kinect track”&lt;/em&gt;&amp;#160; you can do the following:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-hoQkZoonry4/TiF6ztizwQI/AAAAAAAAGo4/rmTdoAG9ae4/s1600-h/rightzoomin21.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="rightzoomin" border="0" alt="rightzoomin" align="left" src="http://lh3.ggpht.com/-sFS0RrNTqLU/TiF60Nt9FaI/AAAAAAAAGo8/M6ITyBkPk7A/rightzoomin_thumb15.png?imgmax=800" width="22" height="31" /&gt;&lt;/a&gt;If you hold your &lt;em&gt;left &lt;/em&gt;hand &lt;em&gt;closer&lt;/em&gt; to your body than your right hand by some 20 cm, it will zoom &lt;em&gt;in&lt;/em&gt; on the location of your &lt;em&gt;right&lt;/em&gt; hand (green “plus” symbol on the right hand symbol).&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-LCTGpy2OcDs/TiF60lZgR0I/AAAAAAAAGpA/2galnCDZ2EY/s1600-h/rightzoomout21.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="rightzoomout" border="0" alt="rightzoomout" align="left" src="http://lh6.ggpht.com/-brKw96YJO1Q/TiF603zRAJI/AAAAAAAAGpE/1HjJ8ax3UlI/rightzoomout_thumb13.png?imgmax=800" width="22" height="31" /&gt;&lt;/a&gt;If you hold your &lt;em&gt;left &lt;/em&gt;hand &lt;em&gt;further &lt;/em&gt;from your body than your right hand by some 20 cm, it will &lt;em&gt;zoom&lt;/em&gt; out on the location of your &lt;em&gt;right&lt;/em&gt; hand (red “minus” symbol on the right hand symbol”) &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-aP9UPp3Pf3w/TiF61WjPy6I/AAAAAAAAGpI/16b9MCUQPb8/s1600-h/rightpan4.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="rightpan" border="0" alt="rightpan" align="left" src="http://lh5.ggpht.com/-cqxG0uByp0g/TiF61xVklNI/AAAAAAAAGpM/8sYO7IF1lhM/rightpan_thumb2.png?imgmax=800" width="22" height="31" /&gt;&lt;/a&gt;If you stretch out both arms and then move your hands, you can pan the map (blue circle with cross will appear on both of the hand symbols). &lt;/p&gt;  &lt;p&gt;Below is a partial screenshot showing Kinect zooming in on Ontario.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-p6kdmcANa-I/TiF63Y0GMGI/AAAAAAAAGpQ/fe0BkuEJZFU/s1600-h/kinecttrack6.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="kinecttrack" border="0" alt="kinecttrack" src="http://lh4.ggpht.com/-y8wiujp3zGY/TiF64KGeZNI/AAAAAAAAGpU/uWd5DW_pGfs/kinecttrack_thumb2.png?imgmax=800" width="628" height="287" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Miscellaneous voice commands:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;“&lt;em&gt;Kinect stop tracking&lt;/em&gt;” will keep following your hands but disable zoom and pan until you say “Kinect track” again &lt;/li&gt;    &lt;li&gt;“&lt;em&gt;Kinect video on&lt;/em&gt;” will show what the Kinect video cam is seeing on the top left of the screen &lt;/li&gt;    &lt;li&gt;“&lt;em&gt;Kinect video off&lt;/em&gt;” will hide video again (you might want to do this as it’s heavy on performance) &lt;/li&gt;    &lt;li&gt;“&lt;em&gt;Kinect shutdown&lt;/em&gt;” will exit the application &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:f988b7f7-aced-4bcf-84b8-6d379b367e2e" class="wlWriterEditableSmartContent"&gt;&lt;div id="d6188042-eaf2-4138-b31c-5296746532d2" style="margin: 0px; padding: 0px; display: inline;"&gt;&lt;div&gt;&lt;a href="http://www.youtube.com/watch?v=Bsec6xF_rNg" target="_new"&gt;&lt;img src="http://lh6.ggpht.com/-R_9qhgRp7vM/TiF64u62BQI/AAAAAAAAGpo/JDEqEQxwCzg/video845bbcf8a951%25255B30%25255D.jpg?imgmax=800" style="border-style: none" galleryimg="no" onload="var downlevelDiv = document.getElementById('d6188042-eaf2-4138-b31c-5296746532d2'); downlevelDiv.innerHTML = &amp;quot;&amp;lt;div&amp;gt;&amp;lt;object width=\&amp;quot;448\&amp;quot; height=\&amp;quot;277\&amp;quot;&amp;gt;&amp;lt;param name=\&amp;quot;movie\&amp;quot; value=\&amp;quot;http://www.youtube.com/v/Bsec6xF_rNg?hl=en&amp;amp;hd=1\&amp;quot;&amp;gt;&amp;lt;\/param&amp;gt;&amp;lt;embed src=\&amp;quot;http://www.youtube.com/v/Bsec6xF_rNg?hl=en&amp;amp;hd=1\&amp;quot; type=\&amp;quot;application/x-shockwave-flash\&amp;quot; width=\&amp;quot;448\&amp;quot; height=\&amp;quot;277\&amp;quot;&amp;gt;&amp;lt;\/embed&amp;gt;&amp;lt;\/object&amp;gt;&amp;lt;\/div&amp;gt;&amp;quot;;" alt=""&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="width:448px;clear:both;font-size:.8em"&gt;The application in action. Since my computer choked on running both Kinect and a screen recorder I actually did this the old fashioned way using a video camera recording the screen ;)&lt;/div&gt;&lt;/div&gt;  &lt;p&gt;&lt;font size="4"&gt;Setting the stage&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;To get this sample to work, you need quite a lot of stuff, both hard- and software. First, of course, you will need a Kinect sensor. Be aware you cannot use a Kinect that comes with an XBox360s – that only has the proprietary orange Kinect connector that may look like and USB connector, but most certainly is not. You will need a &lt;a href="http://www.xbox.com/en-US/Xbox360/Accessories/Kinect/kinectforxbox360" target="_blank"&gt;retail Kinect for Xbox360 sensor&lt;/a&gt;, which includes special USB/power cabling – that will connect to your PC’s ‘ordinary’ USB port&lt;/p&gt;  &lt;p&gt;A word to the wise: if you have a desk top PC, connect Kinect to a back USB port and never, ever use an USB extension cable. Unless you are entertained by very frequent &lt;a href="http://en.wikipedia.org/wiki/Blue_Screen_of_Death" target="_blank"&gt;BSOD&lt;/a&gt;’s. I learned it the hard way - make sure you don’t.&lt;/p&gt;  &lt;p&gt;Then you need quite some stuff to download and install:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The Kinect SDK from the &lt;a href="http://research.microsoft.com/en-us/um/redmond/projects/kinectsdk/download.aspx" target="_blank"&gt;beta SDK page&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.microsoft.com/downloads/en/details.aspx?displaylang=en&amp;amp;FamilyID=3021d52b-514e-41d3-ad02-438a3ba730ba"&gt;Microsoft DirectX® SDK - June 2010&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=bb0f72cb-b86b-46d1-bf06-665895a313c7"&gt;Microsoft Speech Platform Runtime, version 10.2&lt;/a&gt; (x86 edition) &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=1b1604d3-4f66-4241-9a21-90a294a5c9a4&amp;amp;displaylang=en"&gt;Microsoft Speech Platform - Software Development Kit, version 10.2 &lt;/a&gt;(x86 edition) &lt;/li&gt;    &lt;li&gt;&lt;a href="http://go.microsoft.com/fwlink/?LinkId=220942"&gt;Kinect for Windows Runtime Language Pack, version 0.9&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I would also recommend very much installing the &lt;a href="http://kinectcontrib.codeplex.com/" target="_blank"&gt;Kinect project templates for Visual Studio 2010&lt;/a&gt; by the brilliant &lt;a href="http://twitter.com/#!/DennisCode" target="_blank"&gt;Dennis Delimarsky&lt;/a&gt;. I started out by using his Kinect Skeleton template application.&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;MVVMLight 4&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;MVVMLight 4 does not have a binary release yet, as far as I understand, so I pulled the &lt;a href="http://mvvmlight.codeplex.com/" target="_blank"&gt;sources from CodePlex&lt;/a&gt;, compiled the whole stuff and took the following parts:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;GalaSoft.MvvmLight.WPF4.dll &lt;/li&gt;    &lt;li&gt;GalaSoft.MvvmLight.Extras.WPF4.dll &lt;/li&gt;    &lt;li&gt;Microsoft.Practices.ServiceLocation.dll &lt;/li&gt;    &lt;li&gt;System.Windows.Interactivity.dll &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;After building you will find the first file in &lt;em&gt;GalaSoft.MvvmLight\GalaSoft.MvvmLight (NET4)\bin\Release&lt;/em&gt;, the others in &lt;em&gt;GalaSoft.MvvmLight\GalaSoft.MvvmLight.Extras (NET4)\bin\Release&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;Coding4Fun Kinect Toolkit&lt;/font&gt; &lt;/p&gt;  &lt;p&gt;I used only a tiny bit of it, and still have to investigate what it can do, but you can find it here on &lt;a href="http://c4fkinect.codeplex.com/" target="_blank"&gt;CodePlex&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;Setting up the project&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-oWrD_4eFqA4/TiF65ASWIJI/AAAAAAAAGpc/RXq-jBBPsGg/s1600-h/KinectSolution3.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="KinectSolution" border="0" alt="KinectSolution" align="right" src="http://lh6.ggpht.com/-aHho6aB-9c8/TiF659j9qtI/AAAAAAAAGpg/iG92-ZmhLlQ/KinectSolution_thumb1.png?imgmax=800" width="252" height="470" /&gt;&lt;/a&gt;A good programmer is a lazy programmer, so I just selected Dennis Delimarsky’s KinectSkeletonApplication template (you will find it under Visual C#\Windows\Kinect). That creates a nice basic WPF-based Kinect skeleton tracking application that &lt;em&gt;works out of the box&lt;/em&gt; – it projects the video image Kinect sees, and tracks your hands with two red circles. This actually got me off the ground in no time at all, so kudos and thanks to you, Dennis! &lt;/p&gt;  &lt;p&gt;After peeking in Dennis’ code I cleaned the MainPage.xaml and MainPage.xml.cs. Then I added the following references:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Coding4Fun.Kinect.Wpf.dll &lt;/li&gt;    &lt;li&gt;GalaSoft.MvvmLight.WPF4.dll &lt;/li&gt;    &lt;li&gt;GalaSoft.MvvmLight.Extras.WPF4.dll &lt;/li&gt;    &lt;li&gt;Microsoft.Practices.ServiceLocation.dll &lt;/li&gt;    &lt;li&gt;System.Windows.Interactivity.dll &lt;/li&gt;    &lt;li&gt;Microsoft.Speech.dll (on my computer it’s sitting in &lt;em&gt;C:\Program Files\Microsoft Speech Platform SDK\Assembly&lt;/em&gt;) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;As usual, I put assemblies like this in a solution folder called “Binaries” first, to ensure they become part of the solution itself. The net result is displayed right:&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;Main viewmodel&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;MainViewModel is &lt;em&gt;very&lt;/em&gt; simple and is basically nothing more than a Locater:&lt;/p&gt;  &lt;pre&gt;using GalaSoft.MvvmLight;

namespace MapController.ViewModel
{
  public class MainViewModel : ViewModelBase
  {
    private static PoseViewModel _poseViewModelInstance;
    public static PoseViewModel PoseViewModel
    {
      get { return _poseViewModelInstance ?? 
        (_poseViewModelInstance = new PoseViewModel()); }
    }
  }
}&lt;/pre&gt;

&lt;p&gt;This is a pretty standard pattern that makes sure that now matter how much MainViewModels you create by XAML instantiation, there will be one and only one PoseViewModel.&lt;/p&gt;

&lt;p&gt;&lt;font size="4"&gt;The Pose viewmodel&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;PoseViewModel is currently a kind of God class and probably should be broken up should this become a real application one day. This is where most of the Kinect stuff lives. And it’s remarkably small for all the things it actually does. It starts out like this:&lt;/p&gt;

&lt;pre&gt;using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using Coding4Fun.Kinect.Wpf;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Messaging;
using MapController.Messages;
using Microsoft.Research.Kinect.Nui;
using Vector = Microsoft.Research.Kinect.Nui.Vector;

namespace MapController.ViewModel
{
  public class PoseViewModel : ViewModelBase, IDisposable
  {
    private Runtime _runtime;
    private const int Samples = 2;
    private const string DefaultleftHand = &amp;quot;Resources/lefthand.png&amp;quot;;
    private const string DefaultrightHand = &amp;quot;Resources/righthand.png&amp;quot;;

    private readonly List&amp;lt;SkeletonData&amp;gt; _skeletons;

    public PoseViewModel()
    {
      if (!IsInDesignMode)
      {
        _leftHandImage = DefaultleftHand;
        _rightHandImage = DefaultrightHand;
        _skeletons = new List&amp;lt;SkeletonData&amp;gt;();
        _runtime = new Runtime();
        _runtime.SkeletonFrameReady += RuntimeSkeletonFrameReady;
        _runtime.VideoFrameReady += RuntimeVideoFrameReady;
        _runtime.Initialize(
          RuntimeOptions.UseSkeletalTracking | RuntimeOptions.UseColor);
        _runtime.VideoStream.Open(ImageStreamType.Video, 
          2, ImageResolution.Resolution640x480, ImageType.Color);
        Messenger.Default.Register&amp;lt;CommandMessage&amp;gt;(this, ProcessSpeechCommand);
        SpeechController.Initialize();
      }
    }

    void RuntimeVideoFrameReady(object sender, ImageFrameReadyEventArgs e)
    {
      if (ShowVideo)
      {
        Messenger.Default.Send(new VideoFrameMessage {Image = e.ImageFrame.Image});
      }
    }
  }
}&lt;/pre&gt;

&lt;p&gt;Important to note is the Vector alias on top – there is also a System.Windows.Vector and you sure don’t want to use that one. This basically initializes the Kinect “Runtime”, instructs it to use skeleton and video tracking and defines callbacks for that. The SpeechController – I will get to that later – is initialized as well. Note the &lt;em&gt;_skeletons &lt;/em&gt;list – I use that to take the average of a more than one (actually two) skeletons to make the hand tracking a bit more stable.&lt;/p&gt;

&lt;p&gt;Note also the callback “RuntimeVideoFrameReady”- it just shuttles off a frame in a message. A behavior - the DisplayVideoBehavior - will take care of that. I tried to do this with data binding; it works, but gave a less than desirable performance, to put it mildly. &lt;/p&gt;

&lt;p&gt;The ViewModel has 12 properties, which all follow the new MVVMLight 4 syntax:&lt;/p&gt;

&lt;pre&gt;private Vector _lefthandPosition;
public Vector LeftHandPosition
{
  get { return _lefthandPosition; }
  set
  {
    if (!_lefthandPosition.Equals(value))
    {
       _lefthandPosition = value;
       RaisePropertyChanged(() =&amp;gt; LeftHandPosition);
    }
  }
}&lt;/pre&gt;

&lt;p&gt;To prevent this blog post challenging &lt;a href="http://en.wikipedia.org/wiki/War_and_Peace" target="_blank"&gt;Tolstoy’s &amp;quot;War and Peace'”&lt;/a&gt; for length I will only name the rest by name and type: &lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Vector RightHandPosition &lt;/li&gt;

  &lt;li&gt;double LeftHandScale &lt;/li&gt;

  &lt;li&gt;double RightHandScale &lt;/li&gt;

  &lt;li&gt;Visibility HandVisibility &lt;/li&gt;

  &lt;li&gt;string LeftHandImage &lt;/li&gt;

  &lt;li&gt;string RightHandImage &lt;/li&gt;

  &lt;li&gt;bool IsInitialized &lt;/li&gt;

  &lt;li&gt;bool IsTracking &lt;/li&gt;

  &lt;li&gt;bool ShowVideo &lt;/li&gt;

  &lt;li&gt;string LastCommand &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Except for this one, since is does something more – it changes the images for the hands, if neccesary:&lt;/p&gt;

&lt;pre&gt;private bool _isPanning;
public bool IsPanning
{
  get { return _isPanning; }
  set
  {
    if (_isPanning != value)
    {
      _isPanning = value;
      LeftHandImage = _isPanning ? &amp;quot;Resources/leftpan.png&amp;quot; : DefaultleftHand;
      RightHandImage = _isPanning ? &amp;quot;Resources/rightpan.png&amp;quot; : DefaultrightHand;
      RaisePropertyChanged(() =&amp;gt; IsPanning);
    }
  }
}&lt;/pre&gt;

&lt;p&gt;The actual skeleton and pose processing code is surprisingly simple, then:&lt;/p&gt;

&lt;pre&gt;void RuntimeSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
  if (IsInitialized)
  {
    var skeletonSet = e.SkeletonFrame;

    var data = (from s in skeletonSet.Skeletons
                where s.TrackingState == SkeletonTrackingState.Tracked
                select s).FirstOrDefault();

    lock (new object())
    {
      _skeletons.Add(data);
    }
    if (_skeletons.Count &amp;lt; Samples)
    {
      return;
    }
    lock (new object())
    {
      LeftHandPosition = 
        ScaleJoint(_skeletons.Average(JointID.HandLeft)).Position;
      RightHandPosition = 
        ScaleJoint(_skeletons.Average(JointID.HandRight)).Position;
      var spinePosition = 
        ScaleJoint(_skeletons.Average(JointID.Spine)).Position;
      _skeletons.Clear();

      LeftHandScale = RelativePositionToScale(spinePosition, LeftHandPosition);
      RightHandScale = RelativePositionToScale(spinePosition, RightHandPosition);
      HandVisibility = Visibility.Visible;

      if (IsTracking)
      {
        // Both arms stretched: initiate pan
        IsPanning = ((spinePosition.Z - LeftHandPosition.Z) &amp;gt; 0.5 &amp;amp;&amp;amp; 
                    (spinePosition.Z - RightHandPosition.Z) &amp;gt; 0.5);

        if (!IsPanning)
        {
          // Send a zoom in/out message depending on the hand's relative positions 
          var handDist = (LeftHandPosition.Z - RightHandPosition.Z);
          if (handDist &amp;gt; 0.2)
          {
            // left hand pulled back: zoom in
            Messenger.Default.Send(new ZoomMessage 
             { X = RightHandPosition.X, Y = RightHandPosition.Y, Zoom = 1 });

            RightHandImage = &amp;quot;Resources/rightzoomin.png&amp;quot;;
          }
          else if (handDist &amp;lt; -0.2)
          {
            // left hand pushed forward back: zoom out
            Messenger.Default.Send(new ZoomMessage 
              { X = RightHandPosition.X, Y = RightHandPosition.Y, Zoom = -1 });
            RightHandImage = &amp;quot;Resources/rightzoomout.png&amp;quot;;
          }
          else
          {
            RightHandImage = DefaultrightHand;
          }
        }
      }
      else
      {
        IsPanning = false;
      }
    }
  }
}&lt;/pre&gt;

&lt;p&gt;This is really the core of the whole pose recognition performed by this application. The method basically takes a skeleton and puts it in a list. If the desired number of samples are obtained, the average of joints is calculated and scale to the screen. Then it checks if both hands are 50 cm or more before the main body (‘Spine’) – this is assumed to be a panning pose. If that’s not recognized, the method tries to detect if one hand is more than 20 cm before another, so it should initiate a zoom action – this is done by sending a ZoomMessage. If that’s so, the right hand’s image is changed accordingly. The ZoomMessage is so simple I will omit it's source here&lt;/p&gt;

&lt;p&gt;This uses a few other methods:&lt;/p&gt;

&lt;pre&gt;/// &amp;lt;summary&amp;gt;
/// Convert a relative position to a scale
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name=&amp;quot;spinePos&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;
/// &amp;lt;param name=&amp;quot;handPos&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;
/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
private double RelativePositionToScale( Vector spinePos, Vector handPos )
{
  // 30 cm before the chest is 'zero position'
  return 1 - ((spinePos.Z - handPos.Z - 0.3) * 1.8);
}

/// &amp;lt;summary&amp;gt;
/// Scale a joint
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name=&amp;quot;joint&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;
/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
private Joint ScaleJoint(Joint joint)
{
  return joint.ScaleTo(
    (int)SystemParameters.PrimaryScreenWidth, 
    (int)(SystemParameters.PrimaryScreenHeight), 0.5f, 0.5f);
}&lt;/pre&gt;
Both speak pretty much for themselves. The Joint.ScaleTo extension method is coming from Coding4Fun. The ‘Average’ extension methods are my own, and are defined in a separate class: 

&lt;pre&gt;using System.Collections.Generic;
using System.Linq;
using Microsoft.Research.Kinect.Nui;
using Vector = Microsoft.Research.Kinect.Nui.Vector;

namespace MapController
{
  public static class KinectExtensions
  {
    /// &amp;lt;summary&amp;gt;
    /// Calculates the average Vectors of a any number of Vectors
    /// &amp;lt;/summary&amp;gt;
    public static Vector Average(this IEnumerable&amp;lt;Vector&amp;gt; vectors)
    {
      return new Vector {
        X = vectors.Select(p =&amp;gt; p.X).Average(),
        Y = vectors.Select(p =&amp;gt; p.Y).Average(),
        Z = vectors.Select(p =&amp;gt; p.Z).Average(),
        W = vectors.Select(p =&amp;gt; p.W).Average(),
      };
    }

    /// &amp;lt;summary&amp;gt;
    /// Calculates the average of a specific Joint in a number of vectors
    /// &amp;lt;/summary&amp;gt;
    public static Joint Average( this IEnumerable&amp;lt;SkeletonData&amp;gt; data, 
      JointID joint)
    {
      return new Joint
      {
        Position = data.Select(skeleton =&amp;gt; 
          skeleton.Joints[joint].Position).Average()
      };
    }
  }
}&lt;/pre&gt;

&lt;p&gt;Now let's have a look at the GUI. &lt;/p&gt;

&lt;p&gt;&lt;font size="4"&gt;Transparent overlay window&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;WPF poses some unique challenges, one of those being the fact that no WPF objects can be drawn on top of Win32 objects – like, for instance, a WebBrowser control. To circumvent this I created &lt;em&gt;second child window&lt;/em&gt; – full screen, like the first window, but Transparent. So I added KinectOverlay.xaml. This window is launched from MainWindow.xaml.cs as a child window like this: &lt;/p&gt;

&lt;pre&gt;namespace MapController
{
  public partial class MainWindow : Window
  {
    public MainWindow()
    {
      InitializeComponent();
      Loaded += MainWindowLoaded;
    }

    void MainWindowLoaded(object sender, RoutedEventArgs e)
    {
      var w = new KinectOverlay {Owner = this};
      w.Show();
    }
  }
}&lt;/pre&gt;

&lt;p&gt;&lt;font size="4"&gt;MainWindow&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;There's not much in there, actually. Just a browser and some behaviors. &lt;/p&gt;

&lt;pre&gt;&amp;lt;Window xmlns=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot; 
    xmlns:x=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot; 
    xmlns:i=&amp;quot;http://schemas.microsoft.com/expression/2010/interactivity&amp;quot; 
    xmlns:MapController_Behaviors=&amp;quot;clr-namespace:MapController.Behaviors&amp;quot; 
    WindowStyle=&amp;quot;None&amp;quot; WindowState=&amp;quot;Maximized&amp;quot; 
    x:Class=&amp;quot;MapController.MainWindow&amp;quot; Height=&amp;quot;355&amp;quot; Width=&amp;quot;611&amp;quot; 
    ShowInTaskbar=&amp;quot;True&amp;quot; AllowsTransparency=&amp;quot;False&amp;quot;
    DataContext=&amp;quot;{Binding PoseViewModel, Source={StaticResource MainViewModel}}&amp;quot;&amp;gt;
  &amp;lt;i:Interaction.Behaviors&amp;gt;
    &amp;lt;MapController_Behaviors:ZoomBehavior/&amp;gt;
    &amp;lt;MapController_Behaviors:PanBehavior 
        RightHandPosition=&amp;quot;{Binding RightHandPosition, Mode=TwoWay}&amp;quot; 
        LeftHandPosition=&amp;quot;{Binding LeftHandPosition, Mode=TwoWay}&amp;quot;
        IsPanning=&amp;quot;{Binding IsPanning, Mode=TwoWay}&amp;quot;&amp;gt;
    &amp;lt;/MapController_Behaviors:PanBehavior&amp;gt;
  &amp;lt;/i:Interaction.Behaviors&amp;gt;
   &amp;lt;Grid x:Name=&amp;quot;Grid&amp;quot;&amp;gt;
     &amp;lt;WebBrowser x:Name=&amp;quot;Browser&amp;quot; Source=&amp;quot;http://maps.google.com&amp;quot; /&amp;gt;
   &amp;lt;/Grid&amp;gt;
&amp;lt;/Window&amp;gt;&lt;/pre&gt;

&lt;p&gt;As you can see, the actual zoom and pan actions are performed by two behaviors – named “Zoombehavior” and “PanBehavior”. Windows Phone 7 developers, please take note of the fact that WPF allows you to directly bind to behavior dependency properties (this will be possible in the next Windows Phone 7 release as well, since that runs Silverlight 4-ish). Here we come down to the dirty parts of the solution, for the actual map manipulation is performed by simulating mouse position and buttondowns for dragging, and mouse wheel rotations for zoomin in and out. If you are interested in the actual innards of these things, please refer to the &lt;a href="http://www.schaikweb.net/dotnetbyexample/mapcontroller.zip" target="_blank"&gt;sample solution&lt;/a&gt;. Below is just a short description&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The Zoombehavior just waits for a ZoomMessage – and then simulates a zoom in or out by moving the mouse cursor to the position of the right hand, and then simulating a scroll wheel rotation by one position. It only accepts one zoom per 2 seconds to prevent zooming in or out at an uncontrollable rate. &lt;/li&gt;

  &lt;li&gt;The PanBehavior has three dependency properties bound to both hand positions, and IsPanning. If the model says its panning, it calculates the point between left and right hand, and uses that as a dragging origin. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both use a NativeWrapper static class that uses some Win32 api calls – courtesy of &lt;a href="http://www.pinvoke.net/" target="_blank"&gt;pinvoke.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;font size="4"&gt;KinectOverlay&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;Also pretty simple:&amp;#160; A Grid containing a Canvas, which contains standard behavior, and then three images and a text: left hand, right hand, video output, and text place holder to show the last command – all bound to the PoseViewModel. Don’t you just love the power of XAML? ;-)&lt;/p&gt;

&lt;pre style="font-size: 11px"&gt;&amp;lt;Window
    xmlns=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;
    xmlns:x=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;  
    xmlns:i=&amp;quot;http://schemas.microsoft.com/expression/2010/interactivity&amp;quot; 
    xmlns:ei=&amp;quot;http://schemas.microsoft.com/expression/2010/interactions&amp;quot; 
    xmlns:d=&amp;quot;http://schemas.microsoft.com/expression/blend/2008&amp;quot; 
    xmlns:mc=&amp;quot;http://schemas.openxmlformats.org/markup-compatibility/2006&amp;quot; 
    xmlns:MapController_Behaviors=&amp;quot;clr-namespace:MapController.Behaviors&amp;quot; 
    mc:Ignorable=&amp;quot;d&amp;quot; x:Class=&amp;quot;MapController.KinectOverlay&amp;quot;
    Title=&amp;quot;KinectOverlay&amp;quot; Height=&amp;quot;300&amp;quot; Width=&amp;quot;300&amp;quot; WindowStyle=&amp;quot;None&amp;quot; 
    WindowState=&amp;quot;Maximized&amp;quot; Background=&amp;quot;Transparent&amp;quot; AllowsTransparency=&amp;quot;True&amp;quot;&amp;gt;
  &amp;lt;Grid&amp;gt;
  &amp;lt;i:Interaction.Behaviors&amp;gt;
    &amp;lt;ei:FluidMoveBehavior AppliesTo=&amp;quot;Children&amp;quot; Duration=&amp;quot;0:0:0.5&amp;quot;&amp;gt;
    &amp;lt;ei:FluidMoveBehavior.EaseX&amp;gt;
      &amp;lt;SineEase EasingMode=&amp;quot;EaseInOut&amp;quot;/&amp;gt;
    &amp;lt;/ei:FluidMoveBehavior.EaseX&amp;gt;
    &amp;lt;ei:FluidMoveBehavior.EaseY&amp;gt;
      &amp;lt;SineEase EasingMode=&amp;quot;EaseInOut&amp;quot;/&amp;gt;
    &amp;lt;/ei:FluidMoveBehavior.EaseY&amp;gt;
    &amp;lt;/ei:FluidMoveBehavior&amp;gt;
  &amp;lt;/i:Interaction.Behaviors&amp;gt;
  &amp;lt;Canvas Background=&amp;quot;Transparent&amp;quot; 
  DataContext=&amp;quot;{Binding PoseViewModel, Source={StaticResource MainViewModel}}&amp;quot;&amp;gt;

    &amp;lt;!-- Left hand --&amp;gt;
    &amp;lt;Image Source=&amp;quot;{Binding LeftHandImage}&amp;quot; x:Name=&amp;quot;leftHand&amp;quot; Stretch=&amp;quot;Fill&amp;quot;
       Canvas.Left=&amp;quot;{Binding LeftHandPosition.X, Mode=TwoWay}&amp;quot;  
       Canvas.Top=&amp;quot;{Binding LeftHandPosition.Y, Mode=TwoWay}&amp;quot;
       Visibility=&amp;quot;{Binding HandVisibility}&amp;quot; Opacity=&amp;quot;0.75&amp;quot;
       Height=&amp;quot;118&amp;quot; Width=&amp;quot;80&amp;quot; RenderTransformOrigin=&amp;quot;0.5,0.5&amp;quot;&amp;gt;
    &amp;lt;Image.RenderTransform&amp;gt;
      &amp;lt;TransformGroup&amp;gt;
      &amp;lt;ScaleTransform ScaleX=&amp;quot;{Binding LeftHandScale}&amp;quot; 
        ScaleY=&amp;quot;{Binding LeftHandScale}&amp;quot;/&amp;gt;
      &amp;lt;SkewTransform/&amp;gt;
      &amp;lt;RotateTransform/&amp;gt;
      &amp;lt;TranslateTransform X=&amp;quot;-40&amp;quot; Y=&amp;quot;-59&amp;quot;/&amp;gt;
      &amp;lt;/TransformGroup&amp;gt;
    &amp;lt;/Image.RenderTransform&amp;gt;
    &amp;lt;/Image&amp;gt;

    &amp;lt;!-- Right hand --&amp;gt;
    &amp;lt;Image x:Name=&amp;quot;righthand&amp;quot; Source=&amp;quot;{Binding RightHandImage}&amp;quot; Stretch=&amp;quot;Fill&amp;quot;
       Canvas.Left=&amp;quot;{Binding RightHandPosition.X, Mode=TwoWay}&amp;quot;  
       Canvas.Top=&amp;quot;{Binding RightHandPosition.Y, Mode=TwoWay}&amp;quot;
       Visibility=&amp;quot;{Binding HandVisibility}&amp;quot; Opacity=&amp;quot;0.75&amp;quot;
       Height=&amp;quot;118&amp;quot; Width=&amp;quot;80&amp;quot; RenderTransformOrigin=&amp;quot;0.5,0.5&amp;quot;&amp;gt;
    &amp;lt;Image.RenderTransform&amp;gt;
      &amp;lt;TransformGroup&amp;gt;
      &amp;lt;ScaleTransform ScaleX=&amp;quot;{Binding RightHandScale}&amp;quot; 
        ScaleY=&amp;quot;{Binding RightHandScale}&amp;quot;/&amp;gt;
      &amp;lt;SkewTransform/&amp;gt;
      &amp;lt;RotateTransform/&amp;gt;
      &amp;lt;TranslateTransform X=&amp;quot;-40&amp;quot; Y=&amp;quot;-59&amp;quot;/&amp;gt;
      &amp;lt;/TransformGroup&amp;gt;
    &amp;lt;/Image.RenderTransform&amp;gt;
    &amp;lt;/Image&amp;gt;

    &amp;lt;!-- Video --&amp;gt;
    &amp;lt;Image Canvas.Left=&amp;quot;0&amp;quot; Canvas.Top=&amp;quot;100&amp;quot; Width =&amp;quot;360&amp;quot; 
     Visibility=&amp;quot;{Binding ShowVideo, Converter={StaticResource booleanToVisibilityConverter}}&amp;quot;&amp;gt;
    &amp;lt;i:Interaction.Behaviors&amp;gt;
      &amp;lt;MapController_Behaviors:DisplayVideoBehavior/&amp;gt;
    &amp;lt;/i:Interaction.Behaviors&amp;gt;
    &amp;lt;/Image&amp;gt;
    
    &amp;lt;!-- Shows last speech command --&amp;gt;
    &amp;lt;TextBlock Canvas.Left=&amp;quot;10&amp;quot; Canvas.Top=&amp;quot;500&amp;quot; Text=&amp;quot;{Binding LastCommand}&amp;quot;
      FontSize=&amp;quot;36&amp;quot; Foreground=&amp;quot;#FF001900&amp;quot;&amp;gt;&amp;lt;/TextBlock&amp;gt;
  &amp;lt;/Canvas&amp;gt;
  &amp;lt;/Grid&amp;gt;
&amp;lt;/Window&amp;gt;&lt;/pre&gt;

&lt;p&gt;Note that both MainPage.xaml and KinectOverlay.xaml are full-screen with no Window-style but that KinectOverlay.xaml has Background=&amp;quot;Transparent&amp;quot; and AllowsTransparency=&amp;quot;True&amp;quot; attributes. This actually creates the ‘transparent overlay.’&lt;/p&gt;

&lt;p&gt;&lt;font size="4"&gt;Speech recognition&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;If you think, after reading this, that skeleton tracking with Kinect is almost embarrassingly simple, wait till you see speech recognition. I barely scratched the surface I think, but apart from a lot of initialization bruhaha getting Kinect to recognize basic phrases is a simple matter of feeding a couple of &lt;em&gt;strings&lt;/em&gt; to a “Choices” object, feeding that to a “GrammarBuilder” and finally loading that into the “SpeechRecognitionEngine” object. Add a callback to it’s SpeechRecognized property and out come your recognized strings. No calibration, initialization, no hours of ‘training’, nothing – it just works. &lt;/p&gt;

&lt;p&gt;Moving back to the last part of the PoseViewModel: at the very end of it is a static property for the speech controller and a simple switch recognizing the speech commands. &lt;/p&gt;

&lt;pre&gt;#region Speech commands
private static SpeechController _speechControllerInstance;
public SpeechController SpeechController
{
  get { return _speechControllerInstance ?? 
    (_speechControllerInstance = new SpeechController()); }
}

private void ProcessSpeechCommand(CommandMessage command)
{
  switch (command.Command)
  {
    case VoiceCommand.Shutdown:
      {
        Application.Current.Shutdown(); break;
      }
    //etc etc rest of the commands omitted
    case VoiceCommand.VideoOff:
      {
        ShowVideo = false; break;
      }
  }

  LastCommand = command.Command.ToString();
}
#endregion&lt;/pre&gt;

&lt;p&gt;The method ProcessSpeechCommand is called whenever the model receives a CommandMessage – that is issued by the SpeechController. As you can see, the spoken commands are contained in a simple enumeration “VoiceCommand”. Being too lazy to make a proper factory for all the commands, I include the factory methods in CommandMessage as well:&lt;/p&gt;

&lt;pre&gt;using System.Collections.Generic;
using Microsoft.Speech.Recognition;

namespace MapController.Messages
{
  /// &amp;lt;summary&amp;gt;
  /// Command the application is supposed to understand
  /// &amp;lt;/summary&amp;gt;
  public class CommandMessage
  {
    public VoiceCommand Command { get; set; }

    /// &amp;lt;summary&amp;gt;
    /// Factory methods
    /// &amp;lt;/summary&amp;gt;
    private static Dictionary&amp;lt;string, VoiceCommand&amp;gt; _commands;
    public static IDictionary&amp;lt;string, VoiceCommand&amp;gt; Commands
    {
      get
      {
        if (_commands == null)
        {
          _commands = new Dictionary&amp;lt;string, VoiceCommand&amp;gt;
          {
            {&amp;quot;kinect engage&amp;quot;, VoiceCommand.Engage},
            {&amp;quot;kinect stop tracking&amp;quot;, VoiceCommand.StopTracking},
            {&amp;quot;kinect track&amp;quot;, VoiceCommand.Track},
            {&amp;quot;kinect shutdown&amp;quot;, VoiceCommand.Shutdown},
            {&amp;quot;kinect video off&amp;quot;, VoiceCommand.VideoOff},
            {&amp;quot;kinect video on&amp;quot;, VoiceCommand.VideoOn}
          };
        }
        return _commands;
      }
    }

    public static Choices Choices
    {
      get
      {
        var choices = new Choices();
        foreach (var speechcommand in Commands.Keys)
        {
          choices.Add(speechcommand);
        }
        return choices;
      }
    }
  }
}&lt;/pre&gt;

&lt;p&gt;The static Commands property is simple translation table from actual text to VoiceCommand enumeration values. The voice commands themselves (as you see, it’s just &lt;em&gt;strings) &lt;/em&gt;are fed into a Choices object. Now the only thing that’s missing is the actual speech recognition ‘engine’:&lt;/p&gt;

&lt;pre&gt;using System;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Threading;
using GalaSoft.MvvmLight.Messaging;
using MapController.Messages;
using Microsoft.Research.Kinect.Audio;
using Microsoft.Speech.AudioFormat;
using Microsoft.Speech.Recognition;

namespace MapController.ViewModel
{
  public class SpeechController : IDisposable
  {
    private const string RecognizerId = &amp;quot;SR_MS_en-US_Kinect_10.0&amp;quot;;
    private SpeechRecognitionEngine _engine;
    private KinectAudioSource _audioSource;
    private Stream _audioStream;
    private Thread _audioThread;

    public void Initialize()
    {
&lt;font color="#ff0000"&gt;      // Audio recognition needs to happen on a separate thread
      _audioThread = new Thread(InitSpeechRecognition);
      _audioThread.Start();&lt;/font&gt;
    }

    private void InitSpeechRecognition()
    {
      // All kinds on initialization bruhaha directly taken from sample
      _audioSource = new KinectAudioSource
                  {
                    FeatureMode = true,
                    AutomaticGainControl = false,
                    SystemMode = SystemMode.OptibeamArrayOnly
                  };
      var ri =
        SpeechRecognitionEngine.InstalledRecognizers().
          Where(r =&amp;gt; r.Id == RecognizerId).FirstOrDefault();
      _engine = new SpeechRecognitionEngine(ri.Id);
      var gb = new GrammarBuilder { Culture = new CultureInfo(&amp;quot;en-US&amp;quot;) };

     &lt;font color="#ff0000"&gt; // Building my command list
      gb.Append(CommandMessage.Choices);&lt;/font&gt;

      // More initialization bruhaha directly taken from sample
      var g = new Grammar(gb);
      _engine.LoadGrammar(g);
      _engine.SpeechRecognized += SreSpeechRecognized;

      _audioStream = _audioSource.Start();
      _engine.SetInputToAudioStream(_audioStream,
                                    new SpeechAudioFormatInfo(
                                    EncodingFormat.Pcm, 16000, 16, 1,
                                    32000, 2, null));
      _engine.RecognizeAsync(RecognizeMode.Multiple);
    }

&lt;font color="#ff0000"&gt;    private void SreSpeechRecognized(object sender, 
      SpeechRecognizedEventArgs e)
    {
      // Convert spoken text into a command
      if (CommandMessage.Commands.ContainsKey(e.Result.Text))
      {
        Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal,
          new Action(() =&amp;gt;
            Messenger.Default.Send(
               new CommandMessage { 
               Command = CommandMessage.Commands[e.Result.Text] })));
      }
    }&lt;/font&gt;
  }
}&lt;/pre&gt;

&lt;p&gt;This is mostly converted from the basic Speech sample. Only the red things are actually (mostly) mine. Most interesting to note is the fact that for some reason speech recognition needs to be done &lt;em&gt;on a separate thread&lt;/em&gt;. Don’t ask me why – it just needs to. In the middle you can see I feed my Choices-built-from-commands&amp;#160; to a ‘SpeechRecognitionEngine’ going via the ‘GrammarBuilder’ as described earlier, and the SreSpeechRecognized that fires when a speech command is recognized. I call the Messenger back on the UI thread (remember, we are on a separate thread here so nothing bound can be accessed directly) and the result is fired back into the ProcessSpeechCommand of the model, that acts on it as described above.&lt;/p&gt;

&lt;p&gt;Caveat: this speech recognition does not work with an ordinary microphone. Kinect is doing the recognition, apparently. Speech recognition samples without a Kinect connected to your computer simply do not start up.&lt;/p&gt;

&lt;p&gt;&lt;font size="4"&gt;Conclusion and lessons learned&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;As said before, the solution is pretty crude, and so is the user experience. For instance, the application might start with measuring body dimensions. A person with arms shorter that 50 cm would have trouble getting the application to pan, for instance ;-).&amp;#160; But for a first try – with no prior experience – I think it’s a nice start of getting off the ground with Kinect development. I had tremendous fun experimenting with it, although I got a bit distracted from my main passion, i.e. Windows Phone 7. I hope to show this very soon at Vicrea and who knows, maybe this will turn into actual work ;-) &lt;/p&gt;

&lt;p&gt;Apart from the actual knowledge and concepts of the API and Kinect controlling, I have learned the following lessons from this application&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;A good technical implementation of controlling applications with gestures needs an API that is supplied &lt;em&gt;by the controlled application,&amp;#160; or some kind of wrapper&lt;/em&gt;. I now use a pretty crude trick, by simulating mouse actions. For a real gesture controlled application something more is needed &lt;/li&gt;

  &lt;li&gt;When it comes to gesture control, you are basically on your own, without guidelines on ‘how to do things’. For the past 20 years we’ve been using mouse and keyboard to control our computers. This led to a well defined ‘language’ of ‘concepts that has firmly taken root in our consciousness – things like clicking left and right buttons, dragging, using the mouse wheel for zooming in our out, using cursor keys, menu structures (like about/help and tools/properties) – heck, things like CTRL-ALT-DELETE even have become a figure of speech. But when in comes to gestures, &lt;em&gt;there are no rules&lt;/em&gt;, written or unwritten, that describe the ‘logical’ way of zooming and panning a map. Apart from creating the application itself, I had to ‘invent’ the actual poses or gestures. So the logic in zooming out by pulling a hand toward me is mine, but not necessarily yours. A very odd experience. But a fun one. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Sample solution can be obtained &lt;a href="http://www.schaikweb.net/dotnetbyexample/mapcontroller.zip" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5295746446529817470-3155896843536668226?l=dotnetbyexample.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/dotnetbyexample/~4/c2w2JARZ94s" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2011-07-18T15:31:28.268+02:00</atom:updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/-sFS0RrNTqLU/TiF60Nt9FaI/AAAAAAAAGo8/M6ITyBkPk7A/s72-c/rightzoomin_thumb15.png?imgmax=800" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://dotnetbyexample.blogspot.com/2011/07/using-kinect-and-mvvmlight-4-for-some.html</feedburner:origLink></item><item><title>Mogade powered Live Tile high score service for Windows Phone 7</title><link>http://feedproxy.google.com/~r/blogspot/dotnetbyexample/~3/Dx1Bd0H38wM/mogade-powered-live-tile-high-score.html</link><category>WP7NL</category><category>Mogade</category><category>Live Tile</category><category>Windows Phone 7</category><category>WP7</category><category>dotnetmag</category><author>noreply@blogger.com (Joost van Schaik)</author><pubDate>Sat, 18 Jun 2011 08:35:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5295746446529817470.post-831659670086672003</guid><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/x6XkmcQSi6G9f1h5tp8XHkN0WZ0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/x6XkmcQSi6G9f1h5tp8XHkN0WZ0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/x6XkmcQSi6G9f1h5tp8XHkN0WZ0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/x6XkmcQSi6G9f1h5tp8XHkN0WZ0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Those who are following my twitter timeline cannot have missed the fact that I recently published a little game called “&lt;a href="http://social.zune.net/redirect/preferences/askclient?ReturnUrl=http%3a%2f%2fsocial.zune.net%2fredirect%3ftype%3dphoneApp%26id%3d48fd8097-f07e-e011-986b-78e7d1fa76f8" target="_blank"&gt;Catch’em birds&lt;/a&gt;” for &lt;a href="http://www.microsoft.com/windowsphone/en-us/default.aspx" target="_blank"&gt;Windows Phone 7&lt;/a&gt; in the Marketplace. This was mainly a trial project to see if I could bend &lt;a href="http://mvvmlight.codeplex.com/" target="_blank"&gt;MVVMLight&lt;/a&gt; far enough to use in an action&amp;#160; game (result: yes you can). It’s not exactly a smashing success in terms of downloads and sales, and it does not use any of the Windows Phone exclusive features. So I decided to add a Live Tile showing the overall high score and if possible, the player’s rank. I’ve noticed that some people in the Dutch Windows Phone developer community (I won’t mention names here) tend to get particularly competitive when high scores are involved, so maybe this would boost download. And if not, then at least I’d have a lot of fun developing it.&lt;/p&gt;  &lt;p&gt;Catch’em birds features an online leaderboard using the services of &lt;a href="www.mogade.com" target="_blank"&gt;Mogade&lt;/a&gt;. They have a nice and very simple to use library that you can include in your Windows Phone 7 project. You make an account, you define a game, and you define a leaderboard. This will give you 3 keys that you must include in your App and you are ready to go. Samples on their site are quite adequate so I won’t bore you with a repeat of that.&lt;/p&gt;  &lt;p&gt;But now I want to use the same leaderboard services from a Live Tile service. So I defined a solution with an empty ASP.NET Web application project, and deleted all source files except for web.config. In the web.config, I defined four keys:&lt;/p&gt;  &lt;pre&gt;&amp;lt;appSettings&amp;gt;
  &amp;lt;add key=&amp;quot;gamekey&amp;quot; value=&amp;quot;your gamekey here&amp;quot;/&amp;gt;
  &amp;lt;add key=&amp;quot;secret&amp;quot; value=&amp;quot;your game secret here&amp;quot;/&amp;gt;
  &amp;lt;add key=&amp;quot;leaderboard&amp;quot; value=&amp;quot;your leaderboard key here&amp;quot;/&amp;gt;
  &amp;lt;add key=&amp;quot;baseimageurl&amp;quot; value=&amp;quot;Catchembirds/background.png&amp;quot;/&amp;gt;
&amp;lt;/appSettings&amp;gt;&lt;/pre&gt;

&lt;p&gt;The first three are the Mogade keys and are supposed to be secret, so you are not going to include them in your tile request, but ‘somewhere safe’. How safe a plain ole’ web.config is, is subject of discussion but not the point of this article.&lt;/p&gt;

&lt;p&gt;To make Mogade work, you will need &lt;strong&gt;Mogade.Core.dll&lt;/strong&gt; and &lt;strong&gt;Newtonsoft.Json.Net35.dll&lt;/strong&gt;. Beware: &lt;em&gt;use the full .NET version&lt;/em&gt;. This a .NET web application, not a Windows Phone application ;-). You can download these from Mogade or just nick them out of &lt;a href="http://cid-2406abd89008ac37.office.live.com/self.aspx/dotnetbyexample/LiveTileSample.zip" target="_blank"&gt;my sample solution&lt;/a&gt;. Make a reference to those two dll’s and then it’s simply a case of defining a Generic Handler (ashx) and filling in the ProcessRequest method.&lt;/p&gt;

&lt;p&gt;First, I get all the variables I need. My leaderboard is configured to use player name and anonymous live id to recognize the player, so I have to pick those from an URL. The rest comes from the web.config. &lt;/p&gt;

&lt;pre&gt;var userName = context.Request[&amp;quot;username&amp;quot;];
var anid = context.Request[&amp;quot;anid&amp;quot;];
var gameKey = ConfigurationManager.AppSettings[&amp;quot;gamekey&amp;quot;];
var secret = ConfigurationManager.AppSettings[&amp;quot;secret&amp;quot;];
var leaderboard = ConfigurationManager.AppSettings[&amp;quot;leaderboard&amp;quot;];
var baseImageUrl = ConfigurationManager.AppSettings[&amp;quot;baseImageUrl&amp;quot;];&lt;/pre&gt;

&lt;p&gt;The second part opens the base image, calls the Mogade service, waits for it to return data, and draws the result on the image. If the user has not played or has no name entered into the game settings yet, there may be no ranking, so that’s optional. To show that it actually works and the tile is indeed updated multiple times I’ve included code to draw a timestamp on the tile as well. This you will never do in real life, of course.&lt;/p&gt;

&lt;pre&gt;using (var myBitmap = new Bitmap(context.Server.MapPath(baseImageUrl)))
{
  try
  {
    var readyCalled = new ManualResetEvent(false);
    var driver = new Driver(gameKey, secret);

    // Get high score and user ranking
    driver.GetLeaderboard(leaderboard, LeaderboardScope.Overall, 1, 50,
      userName, anid,
      p =&amp;gt;
      {
        if (p.Success)
        {
          using (var g = Graphics.FromImage(myBitmap))
          {
            var font = new Font(&amp;quot;Segoe&amp;quot;, 5, FontStyle.Bold);
            // Draw high score on the tile
            var points = p.Data.Scores[0].Points;
            g.DrawString(&amp;quot;h: &amp;quot; + points.ToString(),
                          font, Brushes.White, new PointF(10, 5));

            // If user has ranking, draw ranking
            if (p.Data.User != null)
            {
              var rank = &amp;quot;r: &amp;quot; + p.Data.User.Rank.ToString();
              var size = g.MeasureString(rank, font);
              g.DrawString(rank.ToString(),font,
                            Brushes.White, 
                            new PointF(173 - size.Width - 10, 5));
            }
            // Draw timestamp - for debugging purposes only
            g.DrawString(
              String.Format(
                new CultureInfo(&amp;quot;en-US&amp;quot;),
                &amp;quot;{0:HH:mm\ndd-MM-yyyy}&amp;quot;, DateTime.UtcNow),
                  font, Brushes.White, new PointF(10, 110));
          }
        }
        // Indicate Mogade call is complete
        readyCalled.Set();
      });

    // Service waits here for Mogade call to complete
    readyCalled.WaitOne();
  }&lt;/pre&gt;

&lt;p&gt;To make the code wait for the call to Mogade to complete, I use a ManualResetEvent. Calling its “WaitOne” method basically hangs the main thread until something else – in this case the anonymous callback from the Mogade GetLeaderBoard method – calls it’s Set method. This little trick I learned from &lt;a href="http://twitter.com/#!/oconijn" target="_blank"&gt;Olaf Conijn&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The final part writes the image back to the stream. There are two important things to note here. First, I output the image as a JPEG of pretty low quality. There are three good reasons for that:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The most important one: I use a &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.shell.shelltileschedule(v=vs.92).aspx" target="_blank"&gt;ShellTileSchedule&lt;/a&gt; to retrieve the tiles, which simply refuses to download anything larger than 80 kb. When I output the tile as PNG, the result is over 120kb and nothing seems to happen. It took me some time to figure out why. &lt;/li&gt;

  &lt;li&gt;You hardly see the difference on a small screen between 80kb PNG and 16kb JPEG &lt;/li&gt;

  &lt;li&gt;Microsoft have tried very hard to make bandwidth and battery usage of Windows Phone 7 as economical as possible, so be user, battery and data plan friendly and keep this kind of repetitive network access as small as possible. &lt;/li&gt;
&lt;/ol&gt;

&lt;pre&gt;    finally
    {
      // Output as JPEG to stay below the 80 kb
      context.Response.ContentType = &amp;quot;image/jpg&amp;quot;;
      using (var ms = new MemoryStream())
      {
        // Select JPEG encoder
        var imgCodec = ImageCodecInfo.GetImageEncoders().Where(
          codec =&amp;gt; codec.FormatID.Equals(ImageFormat.Jpeg.Guid)).FirstOrDefault();
        var parameters = new EncoderParameters();
        parameters.Param[0] = new EncoderParameter(Encoder.ColorDepth, 8);

        // Save on memory stream first, then write bytes to Response
        // Neccesary to get this working on AppHarbor
        myBitmap.Save(ms, imgCodec, parameters);
        var bmpBytes = ms.GetBuffer();
        ms.Close();

        // Add content-length for good measure
        context.Response.AppendHeader(&amp;quot;Content-Length&amp;quot;, bmpBytes.Length.ToString());
        context.Response.BinaryWrite(bmpBytes);
        context.Response.Flush();
        context.Response.End();
      }
    }
  }
}&lt;/pre&gt;

&lt;p&gt;The second thing to note is that I use a little detour writing the resulting image to the Response via a MemoryStream. I could just as easy have written it directly to the context.Response.OutputStream – which I originally did - but I host the service on &lt;a href="http://appharbor.com/" target="_blank"&gt;AppHarbor&lt;/a&gt; and for some reason this gives me a &amp;quot;A generic error occurred in GDI+&amp;quot; error message. Using the MemoryStream solves that problem. &lt;/p&gt;

&lt;p&gt;The result looks something like this:&lt;a href="http://lh4.ggpht.com/-_0Kue_0ouc4/TfzFzDw7RvI/AAAAAAAAGeU/GBgTYKoAQAQ/s1600-h/livetile%25255B2%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="livetile" border="0" alt="livetile" align="left" src="http://lh3.ggpht.com/-8_bw3GEDeWY/TfzFzlCsNMI/AAAAAAAAGeY/8gY4rl25Zek/livetile_thumb.png?imgmax=800" width="177" height="177" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;For my Windows Phone 7 solution I use &lt;a href="http://twitter.com/#!/mark_monster" target="_blank"&gt;Mark Monster&lt;/a&gt;’s &lt;a href="http://mark.mymonster.nl/2010/12/19/solving-3-problems-with-the-shelltileschedule/" target="_blank"&gt;SmartShellTileSchedule&lt;/a&gt; – with a little adaption, i.e. I put a try/catch block in the UpdateTileBeforeOperation because that tended to crash on my phone – but not on my wife’s. I still don’t understand why. I initialize it like this:&lt;/p&gt;

&lt;pre&gt;var mogadeClient = MogadeClient.Initialize(gameId, gameKey);
mogadeClient.Update(null);
new SmartShellTileSchedule
{
  Interval = UpdateInterval.EveryHour,
  MaxUpdateCount = 0,
  RemoteImageUri = new Uri(
    string.Format(
      @&amp;quot;http://www.yourservernamehere.com/LiveTile.ashx?username={0}&amp;amp;anid={1}&amp;quot;,
      userName, mogadeClient.GetUniqueIdentifier()), UriKind.Absolute),
  StartTime = DateTime.Now,
  Recurrence = UpdateRecurrence.Interval
};&lt;/pre&gt;

&lt;p&gt;gameId, gameKey and userName are all variables loaded from the settings ‘somewhere’ in your phone app.&lt;/p&gt;

I had a little doubt whether or not the &lt;a href="http://create.msdn.com/" target="_blank"&gt;App Hub&lt;/a&gt; test team would object to me sending the anonymous live id as part of the tile request but yesterday my live tile enabled version 1.2.0 of Catch'em birds was certified for the Marketplace, so apparently that's allowed. So now there's no reason not to add a Live Tile to your game as well. Make use of this Windows Phone 7 exclusive feature and get your game pinned to start screens all over the world!&lt;/p&gt;

&lt;p&gt;Sample code can be downloaded &lt;a href="http://cid-2406abd89008ac37.office.live.com/self.aspx/dotnetbyexample/LiveTileSample.zip" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5295746446529817470-831659670086672003?l=dotnetbyexample.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/dotnetbyexample/~4/Dx1Bd0H38wM" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2011-07-01T08:37:38.010+02:00</atom:updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/-8_bw3GEDeWY/TfzFzlCsNMI/AAAAAAAAGeY/8gY4rl25Zek/s72-c/livetile_thumb.png?imgmax=800" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://dotnetbyexample.blogspot.com/2011/06/mogade-powered-live-tile-high-score.html</feedburner:origLink></item><item><title>Debugging Windows Phone 7 device network access with just a laptop</title><link>http://feedproxy.google.com/~r/blogspot/dotnetbyexample/~3/wHdM5S1P2RE/debugging-windows-phone-7-device.html</link><category>WP7NL</category><category>Windows Phone 7</category><category>Debugging</category><category>WP7</category><category>dotnetmag</category><author>noreply@blogger.com (Joost van Schaik)</author><pubDate>Tue, 17 May 2011 11:24:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5295746446529817470.post-5828670753173478907</guid><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/b5TUC4VIz24RxQ_BGOjNpNcSZHs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/b5TUC4VIz24RxQ_BGOjNpNcSZHs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/b5TUC4VIz24RxQ_BGOjNpNcSZHs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/b5TUC4VIz24RxQ_BGOjNpNcSZHs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;It’s a strange world. Today I needed to debug an iPad’s web traffic, and ended up getting instructions from the Dutch &lt;a href="http://www.microsoft.com/windowsphone/en-us/default.aspx" target="_blank"&gt;Windows Phone 7&lt;/a&gt; DPE &lt;a href="http://twitter.com/#!/mahoekst" target="_blank"&gt;Matthijs Hoekstra&lt;/a&gt;. To dry run the solution I tried hooking up my own Windows Phone 7 an so was able to see Birdsong actually sending and downloading messages.&lt;/p&gt;  &lt;p&gt;Now there are numerous sources around the internet describing what you should do to get this far but most only show pieces of the puzzle, so I decided to do a quick write-up on how to do this for Windows Phone 7.&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;Prerequisites &lt;/font&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;One laptop running Windows 7 with a WiFi card. I used a HP Probook 4720s &lt;/li&gt;    &lt;li&gt;&lt;a href="http://download.cnet.com/Connectify/3000-18508_4-75024171.html?part=dl-10061477&amp;amp;subj=dl&amp;amp;tag=button" target="_blank"&gt;Connectify&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.getfiddler.com/dl/Fiddler2Setup.exe" target="_blank"&gt;Fiddler2&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;One Windows Phone 7 device (duh) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Make sure you laptop has internet connectivity, either by WiFi or by cable. &lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;Install and configure Connectify&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Download and install Connectify. Now installing this might be a little scary – it wants to install an unverified driver, and the first time I tried it the install got stuck, I had no network connectivity anymore, rebooted, uninstalled Connectify and then painlessly re-installed. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_QXPoKuE9q6k/TdK9T5RtnLI/AAAAAAAAGa0/HJ19EjXGeXw/s1600-h/Connectify%5B3%5D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px 6px 0px 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Connectify" border="0" alt="Connectify" align="left" src="http://lh5.ggpht.com/_QXPoKuE9q6k/TdK9UjDQ4-I/AAAAAAAAGa4/S6iy7QiS6I0/Connectify_thumb%5B1%5D.png?imgmax=800" width="240" height="385" /&gt;&lt;/a&gt;Anyway, it comes with a simple wizard, that asks you for a network name, as password, a connection to share. Connectify runs in the system tray and if you click on it, it pops up like this showed left.&lt;/p&gt;  &lt;p&gt;You can see that my WiFi card now is used by the laptop itself to connect to the internet and as hotspot as well :-). But I could just as easily share a cabled internet connection (as I did this afternoon at my work). You can even see my hotspot’s password, so now you can steal my internet connection when you are in the neighborhood and I leave Connectify running (and then still it gives a bubble notification saying someone connected).&lt;/p&gt;  &lt;p&gt;Your Windows Phone 7 can now already share your laptop’s WiFi connection – if you go to Settings/WiFi you can already see the network showing up. As you can see on the image my HTC 7 Pro has connected to it successfully&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;Install and configure Fiddler&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Just install Fiddler the usual way, but then click Tools/Fiddler options and click tab “Connections”. Right under the box “Fiddler listens on port 8888” there’s a checkbox “Allow remote computers to connect”. Tick that one. close down Fiddler, start it again, and this will bring a Windows Firewall check box to your screen. Check all three checkboxes, and click “Allow Acces”. &lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;&lt;a href="http://lh5.ggpht.com/_QXPoKuE9q6k/TdK9VA-yAbI/AAAAAAAAGa8/hr9YpGbW2k8/s1600-h/IMG_8515%5B5%5D.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="IMG_8515" border="0" alt="IMG_8515" align="right" src="http://lh6.ggpht.com/_QXPoKuE9q6k/TdK9ViwVtNI/AAAAAAAAGbA/ef4DoBNZkaY/IMG_8515_thumb%5B2%5D.jpg?imgmax=800" width="193" height="351" /&gt;&lt;/a&gt;Configure your Windows Phone 7&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Pick up your phone, again, go to Settings/WiFi, connect to the Connectify network if you have not already done so, using the password you picked for it. As the phone is connected, tap your network, locate the “proxy” toggle, click it, use &lt;em&gt;your laptops’ name &lt;/em&gt;as proxy and port 8888 as port, and you are done. Note – both my access point and my laptop are called “JSC7”, but they could be different. Always use your computers’&lt;em&gt; name&lt;/em&gt; for proxy.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;Done&lt;/font&gt;&lt;font size="4"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;You can now spy on your Windows Phone 7’s network. I fired up Birdsong and saw it actually do something&lt;a href="http://lh3.ggpht.com/_QXPoKuE9q6k/TdK9WAYk9cI/AAAAAAAAGbE/KQtIH_ZWXdw/s1600-h/fiddler%5B5%5D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="fiddler" border="0" alt="fiddler" src="http://lh5.ggpht.com/_QXPoKuE9q6k/TdK9WlGwl9I/AAAAAAAAGbI/RLAZxlGAC8I/fiddler_thumb%5B3%5D.png?imgmax=800" width="626" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;Some final words&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;If you have an access point handy, you might skip the whole Connectify stuff, just define your PC as a proxy for that network in your Windows Phone 7 settings and only configure and fire up Fiddler on that PC. But I did not have a wireless AP I could connect my Windows Phone 7 to so I had to resort to Connectify.&lt;/p&gt;  &lt;p&gt;Oh by the way, this works for a iPad as well :-) &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5295746446529817470-5828670753173478907?l=dotnetbyexample.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/dotnetbyexample/~4/wHdM5S1P2RE" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2011-05-17T20:24:26.974+02:00</atom:updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/_QXPoKuE9q6k/TdK9UjDQ4-I/AAAAAAAAGa4/S6iy7QiS6I0/s72-c/Connectify_thumb%5B1%5D.png?imgmax=800" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://dotnetbyexample.blogspot.com/2011/05/debugging-windows-phone-7-device.html</feedburner:origLink></item><item><title>Safe event detachment ‘pattern’ for behaviors</title><link>http://feedproxy.google.com/~r/blogspot/dotnetbyexample/~3/vIRRK3-Krmc/safe-event-detachment-pattern-for.html</link><category>behavior</category><category>WP7NL</category><category>XAML</category><category>Windows Phone 7</category><category>WP7</category><category>dotnetmag</category><author>noreply@blogger.com (Joost van Schaik)</author><pubDate>Wed, 20 Apr 2011 00:51:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5295746446529817470.post-4708791604548375425</guid><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/POFRAB_D6H19KxY4zs3kjRgsHL4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/POFRAB_D6H19KxY4zs3kjRgsHL4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/POFRAB_D6H19KxY4zs3kjRgsHL4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/POFRAB_D6H19KxY4zs3kjRgsHL4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;For the past few weeks I’ve been hacking away at my &lt;a href="http://www.microsoft.com/windowsphone/en-us/default.aspx" target="_blank"&gt;Windows Phone 7&lt;/a&gt; game and noticed something odd. The objective is to intercept moving objects on the screen and drag/flick them to a target – but as the levels progressed interception and movement became ever more difficult and slow. At least that was reported by my #wp7nl fellow members who were kind (or crazy) enough to test drive the game into the higher levels. I won’t mention names here – yet ;-).&lt;/p&gt;  &lt;p&gt;I followed the usual pattern for a behavior – at least, I &lt;em&gt;think&lt;/em&gt; it is the usual pattern&lt;/p&gt;  &lt;pre&gt;using System.Windows;
using System.Windows.Interactivity;

namespace SomeNamespace
{
  public class DemoBehavior : Behavior&amp;lt;FrameworkElement&amp;gt;
  {
    protected override void OnAttached()
    {
      base.OnAttached();
      AssociatedObject.Loaded += AssociatedObjectLoaded;
    }

    void AssociatedObjectLoaded(object sender, RoutedEventArgs e)
    {
      // Hook up a bunch of events to the AssociatedObject
    }

    protected override void OnDetaching()
    {
      AssociatedObject.Loaded -= AssociatedObjectLoaded;
      // Unhook the other events from the AssociatedObject
      base.OnDetaching();
    }
  }
}&lt;/pre&gt;

&lt;p&gt;I had seen this problem before while programming in WPF and indeed – when I put a breakpoint in the first line of the &lt;em&gt;OnDetaching&lt;/em&gt;&amp;#160; override it was never called. Apparently Windows Phone 7 has the same problem. So here was my game, happily creating a lot of moving objects with each 1-2 behaviors attached to it listening to a bunch of events. They were never unhooked when the objects were deleted. So within a few levels the game started eating resources like there’s no tomorrow.&lt;/p&gt;

&lt;p&gt;I modified my behaviors to try to do a general cleanup not only when OnDetaching is called &lt;em&gt;but also when the AssociatedObject is unloaded&lt;/em&gt;. This gave me a pattern which I think might be beneficial to everyone who is working with behaviors in general:&lt;/p&gt;

&lt;pre&gt;using System.Windows;
using System.Windows.Interactivity;

namespace SomeNamespace
{
  public class BetterDemoBehavior : Behavior&amp;lt;FrameworkElement&amp;gt;
  {
    #region Setup
    protected override void OnAttached()
    {
      base.OnAttached();
      AssociatedObject.Loaded += AssociatedObjectLoaded;
      AssociatedObject.Unloaded += AssociatedObjectUnloaded;
    }

    void AssociatedObjectLoaded(object sender, RoutedEventArgs e)
    {
      // Hook up a bunch of events to the AssociatedObject
    }
    #endregion

    #region Cleanup
    private bool _isCleanedUp;

    private void Cleanup()
    {
      if (!_isCleanedUp)
      {
        _isCleanedUp = true;
        AssociatedObject.Loaded -= AssociatedObjectLoaded;
        AssociatedObject.Unloaded -= AssociatedObjectUnloaded;
        // Unhook the other events from the AssociatedObject
      }
    }

    protected override void OnDetaching()
    {
      Cleanup();
      base.OnDetaching();
    }

    void AssociatedObjectUnloaded(object sender, RoutedEventArgs e)
    {
      Cleanup();
    }
    #endregion
  }
}&lt;/pre&gt;

&lt;p&gt;And because I am not very partial to repetitive work, I created a &lt;a href="http://www.schaikweb.net/dotnetbyexample/beh.zip" target="_blank"&gt;snippet&lt;/a&gt; for this piece of code. &lt;/p&gt;

&lt;p&gt;I guess that if both and Windows Phone 7 and WPF have this issue, Silverlight will have it as well. I hope at least this will help people who are, like me, stubborn enough to use Silverlight and &lt;a href="http://mvvmlight.codeplex.com/" target="_blank"&gt;MVVMLight&lt;/a&gt; to develop games for Windows Phone 7 ;-)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5295746446529817470-4708791604548375425?l=dotnetbyexample.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/dotnetbyexample/~4/vIRRK3-Krmc" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2011-04-21T07:58:19.795+02:00</atom:updated><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://dotnetbyexample.blogspot.com/2011/04/safe-event-detachment-pattern-for.html</feedburner:origLink></item><item><title>Preventing objects made invisible by data binding to show up initially</title><link>http://feedproxy.google.com/~r/blogspot/dotnetbyexample/~3/lmBCX2Fy4lY/preventing-objects-made-invisible-by.html</link><category>behavior</category><category>WP7NL</category><category>XAML</category><category>Windows Phone 7</category><category>Silverlight</category><category>WP7</category><category>dotnetmag</category><author>noreply@blogger.com (Joost van Schaik)</author><pubDate>Wed, 13 Apr 2011 00:30:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5295746446529817470.post-2559017126561122540</guid><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/O5_D3ExubGHTBQXB742cJqqqs10/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/O5_D3ExubGHTBQXB742cJqqqs10/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/O5_D3ExubGHTBQXB742cJqqqs10/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/O5_D3ExubGHTBQXB742cJqqqs10/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Currently I am in the process of writing a small &lt;a href="http://www.microsoft.com/windowsphone/en-us/default.aspx" target="_blank"&gt;Windows Phone 7&lt;/a&gt; game . It sports a ‘game over’ panel with a ‘play again’ button and it’s visibility is controlled by a boolean value ‘IsGameOver’ in the ViewModel. My &lt;a href="http://dotnetbyexample.blogspot.com/2010/11/converter-for-showinghiding-silverlight.html" target="_blank"&gt;VisibilityConverter&lt;/a&gt; converts the true and false to Visiblity.Visible and Visibility.Collapsed.&lt;/p&gt;  &lt;p&gt;Although this works well, data binding apparently takes place only &lt;em&gt;after&lt;/em&gt; the complete GUI is loaded, for when the game starts, you see the panel for about half a second before it disappears again. Ugh. &lt;/p&gt;  &lt;p&gt;I did not actually solve this problem, but found a workaround in the following little behavior:&lt;/p&gt;  &lt;pre&gt;using System.Windows;
using System.Windows.Interactivity;

namespace Wp7nl.Behaviors
{
  public class SetInitialOpacityBehavior : Behavior&amp;lt;FrameworkElement&amp;gt;
  {
    protected override void OnAttached()
    {
      AssociatedObject.Loaded += AssociatedObjectLoaded;
      base.OnAttached();
      AssociatedObject.Opacity = InitialOpacity;
    }

    void AssociatedObjectLoaded(object sender, RoutedEventArgs e)
    {
      AssociatedObject.Loaded -= AssociatedObjectLoaded;
      AssociatedObject.Opacity = OpacityAfterLoading;
    }

    #region InitialOpacity
    public const string InitialOpacityPropertyName = "InitialOpacity";

    public int InitialOpacity
    {
      get { return (int)GetValue(InitialOpacityProperty); }
      set { SetValue(InitialOpacityProperty, value); }
    }

    public static readonly DependencyProperty InitialOpacityProperty = 
	  DependencyProperty.Register(
        InitialOpacityPropertyName,
        typeof(int),
        typeof(SetInitialOpacityBehavior),
        new PropertyMetadata(0));
    #endregion

    #region OpacityAfterLoading
    public const string OpacityAfterLoadingPropertyName = "OpacityAfterLoading";

    public int OpacityAfterLoading
    {
      get { return (int)GetValue(OpacityAfterLoadingProperty); }
      set { SetValue(OpacityAfterLoadingProperty, value); }
    }

    public static readonly DependencyProperty OpacityAfterLoadingProperty = 
	DependencyProperty.Register(
      OpacityAfterLoadingPropertyName,
      typeof(int),
      typeof(SetInitialOpacityBehavior),
      new PropertyMetadata(1));
    
    #endregion
  }
}
&lt;/pre&gt;

&lt;p&gt;It basically sets the opacity to 0 when the behavior is attached to the FrameworkElement (which apparently takes place before the element is actually displayed), thereby making the element invisible. After the Loading event has fired, it sets the opacity to the value of the dependency property OpacityAfterLoading - which is default 1. Apparently &lt;em&gt;this&lt;/em&gt; takes place after data binding. Whatever – my ‘game over’ panel does not show up at the start anymore, but only after the game ends. Like it should.&lt;/p&gt;

&lt;p&gt;So if you notice an element showing up initially while it should not, just fire up Blend, drag this behavior on top of it and be done with it.&lt;/p&gt;

&lt;p&gt;This behavior is by no means Windows Phone 7 specific – it would work perfectly in Silverlight and probably WPF too. Be aware, however, that although OpacityAfterLoading is a dependency property, in Windows Phone 7 you cannot data bind it, because it’s currently based on Silverlight 3 which only allow you to bind to classes that do descend from &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.dependencyobject.aspx" target="_blank"&gt;DependencyObject&lt;/a&gt; – which a behavior obviously does not ;-) &lt;/p&gt;

&lt;p&gt;One final concluding note – although this behavior is in the Wp7nl namespace, it currently not in the &lt;a href="http://wp7nl.codeplex.com/" target="_blank"&gt;Wp7nl library&lt;/a&gt; nor the &lt;a href="http://nuget.org/List/Packages/wp7nl" target="_blank"&gt;NuGet&lt;/a&gt; package. But it will be in the next ;-)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5295746446529817470-2559017126561122540?l=dotnetbyexample.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/dotnetbyexample/~4/lmBCX2Fy4lY" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2011-04-20T11:34:57.078+02:00</atom:updated><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://dotnetbyexample.blogspot.com/2011/04/preventing-objects-made-invisible-by.html</feedburner:origLink></item><item><title>Bing Maps control with MVVMLight on Windows Phone 7</title><link>http://feedproxy.google.com/~r/blogspot/dotnetbyexample/~3/_pWooyx8zEc/bing-maps-control-with-mvvmlight-on.html</link><category>MVVM</category><category>Tombstoning</category><category>WP7NL</category><category>XAML</category><category>Windows Phone 7</category><category>MVVM Light</category><category>WP7</category><author>noreply@blogger.com (Joost van Schaik)</author><pubDate>Thu, 07 Apr 2011 23:37:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-5295746446529817470.post-1089560454118692103</guid><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Bup9Bn5gUyC75yRciZTLXXtSteE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Bup9Bn5gUyC75yRciZTLXXtSteE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Bup9Bn5gUyC75yRciZTLXXtSteE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Bup9Bn5gUyC75yRciZTLXXtSteE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;This article appeared originally in the &lt;a href="http://www.dotnetmag.nl/Artikelen/2011/1" target="_blank"&gt;March 2011 issue of .Net Magazine&lt;/a&gt; – in &lt;a href="http://www.dotnetmag.nl/Artikel/1470/Bing-Maps-control-met-MVVMLight-op-WP7" target="_blank"&gt;Dutch&lt;/a&gt;. By popular request I wrote this English translation. Regular readers of this blog may recognize parts of it ;-)&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;A POWERFUL CONTROL WITH A ROBUST ARCHITECTURE&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Not everyone is aware of it yet, but MVVM is becoming the de facto standard for all XAML driven environments – WPF, Silverlight, Microsoft Surface and &lt;a href="http://www.microsoft.com/windowsphone/en-us/default.aspx" target="_blank"&gt;Windows Phone 7&lt;/a&gt;. This article shows how this pattern can be applied and how it can make complex tasks like tombstoning easier. A quite unusual approach is used – driving the Bing Maps control&lt;/p&gt;  &lt;p&gt;&lt;font size="4"&gt;MVVM – theory&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;MVVM stands for Model-View-Viewmodel. Model (business classes) and View (XAML) are connected by a ViewModel – which was dubbed ‘basically a value convertor on steroids’ by Josh Smith. The ViewModel is a class that provides properties from the Model in such a way that the contents can be displayed using data binding.&lt;/p&gt;  &lt;p&gt;Since data binding can work two-way, a change in the ViewModel is automatically displayed in the View, and a change in the View (on user input) is automatically populated to the model. The View can also bind to &lt;em&gt;commands&lt;/em&gt;: these are methods in the ViewModel called as a result of an event in the View (for example, a button is pressed), and that in some way manipulate the underlying Model. In theory the companion ‘code behind’ files to the XAML are completely empty. This approach has two distinct advantages:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;     &lt;div align="left"&gt;The ViewModel can be unit-tested, something that’s next to impossible when the logic is put in the code behind in the traditional way.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="left"&gt;The View itself – the XAML – is totally devoid of code. Therefore a designer, who is not interested in code, can happily style the and adapt the View without breaking functionality.&lt;/div&gt;   &lt;/li&gt; &lt;/ol&gt;  &lt;p align="left"&gt;&lt;font size="4"&gt;MVVM – in practice, on Windows Phone 7&lt;/font&gt;&lt;/p&gt;  &lt;p align="left"&gt;Windows Phone 7 – based on Silverlight 3 – poses some challenges. Property binding is a breeze, but command binding is not – for the simple reason that the classes supporting command binding are missing. Another challenge is the fact that Windows Phone 7 applications can be interrupted at any moment – because the user hits the ‘Start’ button, for instance. When this occurs, the application state must be preserved – ‘tombstoned’.&lt;/p&gt;  &lt;p align="left"&gt;CodePlex host various frameworks that enable MVVM support in Silverlight and Windows Phone 7. Two of the most well-known are (in no particular order) &lt;a href="http://mvvmlight.codeplex.com/" target="_blank"&gt;MVVMLight&lt;/a&gt; by &lt;a href="www.twitter.com/lbugnion" target="_blank"&gt;Laurent Bugnion&lt;/a&gt; and &lt;a href="http://caliburnmicro.codeplex.com/" target="_blank"&gt;Caliburn Micro&lt;/a&gt; by &lt;a href="http://twitter.com/#!/eisenbergeffect" target="_blank"&gt;Rob Eisenberg&lt;/a&gt;. Both have their distinct advantages and disadvantages, both have their ardent advocates. In this article MVVMLight is used.&lt;/p&gt;  &lt;p align="left"&gt;In the next sample all classes are put together in one project – in practice certain classes will get their own assemblies. But the purpose of this article is to show the idea behind using MVVM.&lt;/p&gt;  &lt;p align="left"&gt;&lt;font size="4"&gt;Base application&lt;/font&gt;&lt;/p&gt;  &lt;p align="left"&gt;&lt;a href="http://lh4.ggpht.com/_QXPoKuE9q6k/TZ6tEenQDfI/AAAAAAAAGZs/9ySk6yxFOQ8/s1600-h/designedapp2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="designedapp" border="0" alt="designedapp" align="right" src="http://lh3.ggpht.com/_QXPoKuE9q6k/TZ6tFGC8gKI/AAAAAAAAGZw/OHdkRdO9EFk/designedapp_thumb.png?imgmax=800" width="160" height="244" /&gt;&lt;/a&gt;The way Bing Maps and MVVMLight can act together will be demonstrated using a simple “MapBindingDemo” app. This consists of a Bing Maps control, two buttons to select map types, and a TextBlock to display the name of the selected map. Map manipulation by using pinch zoom, pan and double tap are all included for free, courtesy of the Bing Maps control. The easiest way to get started is to create an empty “Windows Phone Application” in Visual Studio 2010. Then open this application in Blend, enter “Map” in the Assets box and drag the map on the design pane. Add controls until the result looks like displayed on the the right.&lt;/p&gt;  &lt;p align="left"&gt;&amp;#160;&lt;/p&gt;  &lt;p align="left"&gt;&amp;#160;&lt;/p&gt;  &lt;p align="left"&gt;In XAML, the result should look like this:&lt;/p&gt;  &lt;pre&gt;&amp;lt;Grid x:Name=&amp;quot;ContentPanel&amp;quot; Grid.Row=&amp;quot;1&amp;quot; Margin=&amp;quot;12,0,12,0&amp;quot;/&amp;gt;
&amp;lt;Grid Grid.Row=&amp;quot;1&amp;quot;&amp;gt;
  &amp;lt;Grid.ColumnDefinitions&amp;gt;
    &amp;lt;ColumnDefinition Width=&amp;quot;0.167*&amp;quot;/&amp;gt;
    &amp;lt;ColumnDefinition Width=&amp;quot;0.667*&amp;quot;/&amp;gt;
    &amp;lt;ColumnDefinition Width=&amp;quot;0.167*&amp;quot;/&amp;gt;
  &amp;lt;/Grid.ColumnDefinitions&amp;gt;
  &amp;lt;Grid.RowDefinitions&amp;gt;
    &amp;lt;RowDefinition Height=&amp;quot;0.13*&amp;quot;/&amp;gt;
    &amp;lt;RowDefinition Height=&amp;quot;0.87*&amp;quot;/&amp;gt;
  &amp;lt;/Grid.RowDefinitions&amp;gt;
  &amp;lt;Microsoft_Phone_Controls_Maps:Map Grid.Row=&amp;quot;1&amp;quot; Grid.ColumnSpan=&amp;quot;3&amp;quot;/&amp;gt;
  &amp;lt;Button Content=&amp;quot;&amp;lt;&amp;quot;/&amp;gt;
  &amp;lt;Button Content=&amp;quot;&amp;gt;&amp;quot; Grid.Column=&amp;quot;2&amp;quot;/&amp;gt;
  &amp;lt;TextBlock Grid.Column=&amp;quot;1&amp;quot; TextWrapping=&amp;quot;Wrap&amp;quot; Text=&amp;quot;TextBlock&amp;quot; 
    Margin=&amp;quot;0,23,0,0&amp;quot; HorizontalAlignment=&amp;quot;Center&amp;quot;/&amp;gt;
&amp;lt;/Grid&amp;gt;&lt;/pre&gt;

&lt;p&gt;Those who are stubborn enough to venture here without using Blend: the project should have a reference to Windows.Controls.Phone.Maps and the namespace declarations of the PhoneApplicationPage should include the following declarations:&lt;/p&gt;

&lt;pre style="font-size: 11px"&gt;xmlns:Microsoft_Phone_Controls_Maps=
   &amp;quot;clr-namespace:Microsoft.Phone.Controls.Maps;assembly=Microsoft.Phone.Controls.Maps&amp;quot;&lt;/pre&gt;

&lt;p&gt;Another thing to take into consideration is the fact that Bing Maps Control usages requires &lt;em&gt;credentials&lt;/em&gt;. These can be created using &lt;a href="https://www.bingmapsportal.com/" target="_blank"&gt;this website&lt;/a&gt;.The credentials should be included in the Map Control’s &lt;em&gt;CredentialsProvider&lt;/em&gt; property. The Uri the site asks for does not matter – that’s only important when the Bing Maps control is used in a web site context, which is obviously not the case in a Windows Phone 7 app.&lt;/p&gt;

&lt;p&gt;&lt;font size="4"&gt;Bing Maps Control and TileSource&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;The Bing Maps Control is pretty flexible and powerful, and can show both vector and raster maps. This example concentrates on the latter. It’s important to know the control has three major settings as far as raster maps are concerned: “Road”,&amp;#160; “Aerial” and the least known – “Mercator”. When Mercator is set, the control won’t download any map data by itself – the developer should supply the logic in a class implementing Microsoft.Phone.Controls.Maps.TileSource. Only the GetUri method needs to be overridden. The Bing Maps controls supplies &lt;a href="http://lh5.ggpht.com/_QXPoKuE9q6k/TZ6tFS8xL8I/AAAAAAAAGZ0/ierWPO-7VpQ/s1600-h/mapclasses5.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="mapclasses" border="0" alt="mapclasses" align="right" src="http://lh3.ggpht.com/_QXPoKuE9q6k/TZ6tFzsBPEI/AAAAAAAAGZ4/EiMPJPjD7dw/mapclasses_thumb3.png?imgmax=800" width="405" height="228" /&gt;&lt;/a&gt;three parameters to this method: x, y and zoomlevel. At level 1, the world is a square of 2x2=4 tiles of 256x256 pixels each. On level 2, there are 16 tiles, on level 3 there are 64, etc. The method GetUri should convert these three numbers into an Uri leading to a suitable image. For geo nuts like me a piece of cake, for the rest of the world possible a load of gobbledygook. This is by no means a problem when trying to understand MVVM - the TileSource code is all included in this article. The application sports a folder &amp;quot;Maps&amp;quot; which will include this code.&lt;/p&gt;

&lt;p&gt;In this article, the code for the various TileSources is showed in a single code file to give an easier overview. In real-world development, only code generators put multiple classes in one file, eh?&lt;/p&gt;

&lt;pre&gt;using System;
using Microsoft.Phone.Controls.Maps;

namespace MapBindingDemo.Maps
{
  public abstract class BaseTileSource : TileSource, 
    IEquatable&amp;lt;BaseTileSource&amp;gt;
  {
    public string Name { get; set; }


    public bool Equals(BaseTileSource other)
    {
      return other != null &amp;amp;&amp;amp; other.Name.Equals(Name);
    }

    public override bool Equals(object obj)
    {
      return Equals(obj as BaseTileSource);
    }
  }

//------------------------

  public abstract class BaseBingSource : BaseTileSource
  {
    private static string TileXYToQuadKey(int tileX, int tileY, int levelOfDetail)
    {
      var quadKey = new StringBuilder();
      for (var i = levelOfDetail; i &amp;gt; 0; i--)
      {
        char digit = '0';
        int mask = 1 &amp;lt;&amp;lt; (i - 1);
        if ((tileX &amp;amp; mask) != 0) digit++;
        if ((tileY &amp;amp; mask) != 0)
        {
          digit++;
          digit++;
        }
        quadKey.Append(digit);
      }
      return quadKey.ToString();
    }

    public override Uri GetUri(int x, int y, int zoomLevel)
    {
      if (zoomLevel &amp;gt; 0)
      {
        string quadKey = TileXYToQuadKey(x, y, zoomLevel);
        string veLink = string.Format(UriFormat,
           new object[] { quadKey[quadKey.Length - 1], quadKey });
        return new Uri(veLink);
      }
      return null;
    }
  }
  
//------------------------  
  
  public class BingRoad : BaseBingSource
  {
    public BingRoad()
    {
      UriFormat = &amp;quot;http://r{0}.ortho.tiles.virtualearth.net/tiles/r{1}.png?g=203&amp;quot;;
    }
  }
  
//------------------------  

  public class BingAerial : BaseBingSource
  {
    public BingAerial()
    {
      UriFormat = &amp;quot;http://h{0}.ortho.tiles.virtualearth.net/tiles/h{1}.jpeg?g=203&amp;quot;;
    }
  }

//------------------------

  public class OsmaRender : BaseTileSource
  {
    public OsmaRender()
    {
      UriFormat = &amp;quot;http://{0}.tah.openstreetmap.org/Tiles/tile/{1}/{2}/{3}.png&amp;quot;;
    }

    private readonly static string[] TilePathPrefixes = 
      new[] { &amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;, &amp;quot;d&amp;quot;, &amp;quot;e&amp;quot;, &amp;quot;f&amp;quot; };

    public override Uri GetUri(int x, int y, int zoomLevel)
    {
      if (zoomLevel &amp;gt; 0)
      {       
        var url = string.Format(UriFormat, 
          TilePathPrefixes[(y%3) + (3*(x%2))], zoomLevel, x, y);
        return new Uri(url);
      }
      return null;
    }
  }
  
//------------------------  

  public class Mapnik : BaseTileSource
  {
    public Mapnik()
    {
      UriFormat = &amp;quot;http://{0}.tile.openstreetmap.org/{1}/{2}/{3}.png&amp;quot;;
    }

    private readonly static string[] TilePathPrefixes = new[] { &amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot; };

    public override Uri GetUri(int x, int y, int zoomLevel)
    {
      if (zoomLevel &amp;gt; 0)
      {
        var url = string.Format(UriFormat, TilePathPrefixes[y%3], zoomLevel, x, y);
        return new Uri(url);
      }
      return null;
    }
  }
  
//------------------------  

  public enum GoogleType
  {
    Street     ='m',
    Hybrid     ='y',
    Satellite    ='s',
    Physical     ='t',
    PhysicalHybrid ='p',
    StreetOverlay  ='h',
    WaterOverlay   ='r'
  }

//------------------------  
  
  public class Google : BaseTileSource
  {
    public Google()
    {
      MapType = GoogleType.PhysicalHybrid;
      UriFormat = @&amp;quot;http://mt{0}.google.com/vt/lyrs={1}&amp;amp;z={2}&amp;amp;x={3}&amp;amp;y={4}&amp;quot;;
    }

    public GoogleType MapType { get; set; }

    public override Uri GetUri(int x, int y, int zoomLevel)
    {
      return new Uri( 
        string.Format(UriFormat, (x % 2) + (2 * (y % 2)),
        (char)MapType, zoomLevel, x, y) );
    }
  } 
}&lt;/pre&gt;

&lt;p&gt;The starting point is a base class “BaseTileSource” which only adds a Name property and an Equals method that compares by name – a quite naïve implementation, but sufficient for this purpose. A subclass “BaseBingSource” contains most of the heavy lifting for the Bing Maps calculations, so two pretty simple subclasses “BingAerial” and “BingRoad” are all that’s needed to implement Bing Aerial and Bing Road. So far the net result is a quite complicated way to get exactly the same result as the standard Bing Maps Control, but the fun starts when two well-known open source OpenStreetMap mapservers are added – OsmaRender and Mapnik. And of course my personal favorite ‘nag the competition’ option: Google Maps. &lt;/p&gt;

&lt;p&gt;As stated before, the Bing Maps Control should operate in Mercator mode. The way to do this is described below:&lt;/p&gt;

&lt;pre&gt;&amp;lt;Microsoft_Phone_Controls_Maps:Map                 
    CredentialsProvider=&amp;quot;your_credentials_here&amp;quot;&amp;gt;               
    &amp;lt;Microsoft_Phone_Controls_Maps:Map.Mode&amp;gt;
        &amp;lt;MSPCMCore:MercatorMode/&amp;gt;
    &amp;lt;/Microsoft_Phone_Controls_Maps:Map.Mode&amp;gt;
&amp;lt;/Microsoft_Phone_Controls_Maps:Map&amp;gt;&lt;/pre&gt;

&lt;p&gt;The namespace “MSPCMCore” is declared in the PhoneApplicationPage tag like this:&lt;/p&gt;

&lt;pre style="font-size: 11px"&gt;&amp;quot;clr-namespace:Microsoft.Phone.Controls.Maps.Core;assembly=Microsoft.Phone.Controls.Maps&amp;quot;&lt;/pre&gt;

&lt;p&gt;&lt;font size="4"&gt;Setup MVVMLight&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://lh4.ggpht.com/_QXPoKuE9q6k/TZ6tGZeM7qI/AAAAAAAAGZ8/Z09ePDyU5Cw/s1600-h/Solution16.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Solution1" border="0" alt="Solution1" align="right" src="http://lh3.ggpht.com/_QXPoKuE9q6k/TZ6tGxSlpQI/AAAAAAAAGaA/VRhtIjW8zyo/Solution1_thumb4.png?imgmax=800" width="159" height="284" /&gt;&lt;/a&gt;The framework itself contains of two assemblies: GalaSoft.MvvmLight.WP7.dll andGalaSoft.MvvmLight.Extras.WP7.dll. These can be downloaded from &lt;a href="http://mvvmlight.codeplex.com/" target="_blank"&gt;CodePlex&lt;/a&gt;. Apart from those, the assembly System.Windows.Interactivity.dll is necessary as well – this can be found in the Expression Blend SDK and is locaties either in 

  &lt;br /&gt;&lt;font size="1"&gt;&lt;strong&gt;&amp;lt;drive&amp;gt;:\Program Files\Microsoft SDKs\Expression\Blend\Windows Phone\v7.0\Libraries&lt;/strong&gt;&lt;/font&gt; 

  &lt;br /&gt;or in 

  &lt;br /&gt;&lt;strong&gt;&lt;font size="1"&gt;&amp;lt;drive&amp;gt;:\Program Files (x86)\Microsoft SDKs\Expression\Blend\Windows Phone\v7.0\Libraries&lt;/font&gt; 

    &lt;br /&gt;&lt;/strong&gt;when you have a 64 bit OS, which is becoming ever more commonplace these days. It’s good practice to put these assemblies in a &lt;em&gt;solution&lt;/em&gt; &lt;em&gt;folder&lt;/em&gt; to make sure they remain associated with the solution – it makes working with multiple developers on a single Windows Phone 7 project utilizing a source control mechanism a lot easier. In this sample a folder “Binaries” is used to that effect. The project needs to have a reference to the three assemblies mentioned above, and the solution now should look like displayed to the right.&lt;/p&gt;

&lt;p&gt;&lt;font size="4"&gt;Map app ViewModel&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;An MVVMLight ViewModel is a child class of the most originally named “ViewModelBase” class. A number of properties are defined within this application’s ViewModel: ZoomLevel, MapCenter, AvailableMaps and CurrentMap. In addition, it has a number of commands: one for moving a map definition ahead, and one for moving back. The ViewModel looks like this:&lt;/p&gt;

&lt;pre&gt;using System.Collections.Generic;
using System.Device.Location;
using System.Windows.Input;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using MapBindingDemo.Maps;
using MapBindingDemo.Serialization;

namespace MapBindingDemo.ViewModel
{
  public class MvvmMap : ViewModelBase
  {
    public MvvmMap()
    {
      _availableMapSources = new List&amp;lt;BaseTileSource&amp;gt; 
      {
        new BingAerial{ Name = &amp;quot;Bing Aerial&amp;quot;},
        new BingRoad {Name = &amp;quot;Bing Road&amp;quot;},
        new Mapnik {Name = &amp;quot;OSM Mapnik&amp;quot;},
        new OsmaRender {Name = &amp;quot;OsmaRender&amp;quot;},
        new Google {Name = &amp;quot;Google Hybrid&amp;quot;, MapType = GoogleType.Hybrid},
        new Google {Name = &amp;quot;Google Street&amp;quot;, MapType = GoogleType.Street},
      };
    }

    private GeoCoordinate _mapCenter;
    public GeoCoordinate MapCenter
    {
      get { return _mapCenter; }
      set
      {
        if (_mapCenter == value) return;
        _mapCenter = value;
        RaisePropertyChanged(&amp;quot;MapCenter&amp;quot;);
      }
    }

    private double _zoomLevel;
    public double ZoomLevel
    {
      get
      {
        return _zoomLevel;
      }
      set
      {
        if (value == _zoomLevel) return;
        if (value &amp;gt;= 1)
        {
          _zoomLevel = value;
        }
        RaisePropertyChanged(&amp;quot;ZoomLevel&amp;quot;);
      }
    }

    private BaseTileSource _currentMap;
    public  BaseTileSource CurrentMap
    {
      get
      {
        if (_currentMap == null &amp;amp;&amp;amp; 
          _availableMapSources != null &amp;amp;&amp;amp; 
          _availableMapSources.Count &amp;gt; 0)
        {
          _currentMap = _availableMapSources[0];
        }
        return _currentMap;
      }
      set
      {
        if (value.Equals(CurrentMap)) return;
        {
          _currentMap = value;
        }
        RaisePropertyChanged(&amp;quot;CurrentMap&amp;quot;);
      }
    }

    private List&amp;lt;BaseTileSource&amp;gt; _availableMapSources;
    [DoNotSerialize]
    public List&amp;lt;BaseTileSource&amp;gt; AvailableMapSources
    {
      get
      {
        return _availableMapSources;
      }
      set
      {
        _availableMapSources = value;
        RaisePropertyChanged(&amp;quot;AvailableMapSources&amp;quot;);
      }
    }

    public ICommand NextMap
    {
      get
      {
        return new RelayCommand(() =&amp;gt;
        {
          var newIdx = AvailableMapSources.IndexOf(CurrentMap) + 1 ;
          CurrentMap = 
            AvailableMapSources[newIdx &amp;gt; AvailableMapSources.Count - 1? 0 : newIdx];
        });
      }
    }

    public ICommand PreviousMap
    {
      get
      {
        return new RelayCommand(() =&amp;gt;
        {
          var newIdx = AvailableMapSources.IndexOf(CurrentMap) -1;
          CurrentMap = 
            AvailableMapSources[newIdx &amp;lt; 0 ? 
             AvailableMapSources.Count - 1 : newIdx];
        });
      }
    }
     
    private static MvvmMap _instance;
    public static MvvmMap Instance
    {
      get { return _instance; }
      set { _instance = value; }
    }

    public static void CreateNew()
    {
      _instance = new MvvmMap();
    }
  }
}&lt;/pre&gt;

&lt;p&gt;&lt;font size="4"&gt;Hooking up ViewModel and user interface using Blend&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_QXPoKuE9q6k/TZ6tHM0vsfI/AAAAAAAAGaE/PxfHtOEcFfc/s1600-h/data4.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="data" border="0" alt="data" align="right" src="http://lh5.ggpht.com/_QXPoKuE9q6k/TZ6tHlFYxiI/AAAAAAAAGaI/oSQSv_9ESvw/data_thumb2.png?imgmax=800" width="266" height="143" /&gt;&lt;/a&gt;Using databinding, ZoomLevel and MapCenter can be hooked up without any special measures to a Bing Maps control, while the TextBlock “TextBlock” should display the map name. The easiest way to accomplish this is using Expression Blend. A free version for Windows Phone is included with the Windows Phone 7 tools. When Blend has finished loading your projects, notice the three tabs to the upper right: &amp;quot;Properties&amp;quot;, &amp;quot;Resources&amp;quot; and &amp;quot;Data&amp;quot;. Click the encircled symbol and a menu appears, which contains the option “Create Object Data Source. When this is selected, a popup appears with all the objects in the solution. Click MapBindingDemo, then MapBindingDemo.ViewModel, and finally MvvmMap. To the right, the properties of MvvmMap are displayed. Drag the “Instance” property to the Grid “LayoutRoot” in the “Objects and Timeline” panel at the left side. Blend shows the text “Data bind LayoutRoot.DataContext to Instance”. Release the mouse button and – done. Data binding.&lt;/p&gt;

&lt;p&gt;At the right bottom, a panel “Data context” has appeared. Drag property “Name” from “CurrentMap” on top of the TextBlock. The contents of the TextBlock immediately changes to “Bing Aerial”. And that’s correct, since the ViewModel code shows that when no map is selected, the first map in “AvailableMaps” should be selected, which is indeed Bing Aerial.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_QXPoKuE9q6k/TZ6tHy4zVeI/AAAAAAAAGaM/3QMZwTuchvM/s1600-h/ObjectsAndTimeLine%5B2%5D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="ObjectsAndTimeLine" border="0" alt="ObjectsAndTimeLine" align="left" src="http://lh5.ggpht.com/_QXPoKuE9q6k/TZ6tIO82UsI/AAAAAAAAGaQ/Eris5JGukzg/ObjectsAndTimeLine_thumb%5B1%5D.png?imgmax=800" width="165" height="190" /&gt;&lt;/a&gt;Go back to the “Objects and Timeline” panel, and select the object “Map”. To get there, you will first need to expand “Layoutroot” and “Grid”. Data bind the “MapCenter” property of the ViewModel to the “Center” property of the map by dragging MapCenter on top of the Bing Maps controls – a popup appears, in which you can select the “Center” property. &lt;/p&gt;

&lt;p&gt;For some strange reason I could not get Blend to databind “ZoomLevel” this way – it only wants to bind to “Content”. To work around this: select &lt;a href="http://lh5.ggpht.com/_QXPoKuE9q6k/TZ6tIk_sBUI/AAAAAAAAGaU/sqGyDeqoPik/s1600-h/advancedoptions%5B1%5D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="advancedoptions" border="0" alt="advancedoptions" align="right" src="http://lh6.ggpht.com/_QXPoKuE9q6k/TZ6tIw5Y5GI/AAAAAAAAGaY/VEWZa243efc/advancedoptions_thumb%5B1%5D.png?imgmax=800" width="175" height="292" /&gt;&lt;/a&gt;tab “Properties”. Then expand “Miscellaneous”. All the way down you will see the “ZoomLevel” property. Right next to it is a little square: click this, and this will yield and menu which contains the option “Data Binding”. Select this, and then select property “ZoomLevel” of the model in the popup that follows. &lt;/p&gt;

&lt;p&gt;Now switch to the XAML view, and notice that in the Bing Maps Control Center and Zoomlevel properties are bound: Center=&amp;quot;{Binding MapCenter}&amp;quot; ZoomLevel=&amp;quot;{Binding ZoomLevel}&amp;quot;. To make the binding function properly, change this to Center=&amp;quot;{Binding MapCenter, &lt;strong&gt;Mode=TwoWay&lt;/strong&gt;}&amp;quot; ZoomLevel=&amp;quot;{Binding ZoomLevel, &lt;strong&gt;Mode=TwoWay&lt;/strong&gt;}”. This can be done from Blend as well, but this way is quicker. &lt;/p&gt;

&lt;p&gt;Databinding command utilizes the MVVMLight EventToCommand behavior. Type “Event” in the “Search” box top left and the EventToCommand behavior appears. Drag this on both the “&amp;lt;” and the “&amp;gt;” button. Then drag “PreviousCommand” from the ViewModel on top of the EventToCommand below the “&amp;lt;” button (inthe Objects and Timeline panel). “NextCommand” is databound in the same way to the “&amp;gt;” button. Hit F5 in Blend, the emulator appears and when “&amp;gt;” and “&amp;lt;” the text in the TextBlock should change. But the map does not play along – even more, there is absolutely no map visible. That’s because there’s no TileSource associated with it.&lt;/p&gt;

&lt;p&gt;&lt;font size="4"&gt;Attached Dependency Properties – plumbing holes in data binding&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;Binding a TileSource to a Bing Maps control is not possible, because there’s no fitting property. Fortunately XAML includes attached dependency properties – these can be regarded as the property equivalent of extension methods. Back to Visual Studio, where an attached dependency property will be created in the folder “ViewModel”&lt;/p&gt;

&lt;pre&gt;using System.Windows;
using MapBindingDemo.Maps;
using Microsoft.Phone.Controls.Maps;

namespace MapBindingDemo.ViewModel
{
  public static class BindingHelpers
  {
    //Used for binding a single TileSource object to a Bing Maps control
    #region TileSourceProperty

    public static readonly DependencyProperty TileSourceProperty =
      DependencyProperty.RegisterAttached(&amp;quot;TileSource&amp;quot;, typeof(TileSource),
      typeof(BindingHelpers), new PropertyMetadata(SetTileSourceCallback));

    // Called when TileSource is retrieved
    public static TileSource GetTileSource(DependencyObject obj)
    {
      return obj.GetValue(TileSourceProperty) as TileSource;
    }

    // Called when TileSource is set
    public static void SetTileSource(DependencyObject obj, TileSource value)
    {
      obj.SetValue(TileSourceProperty, value);
    }

    //Called when TileSource is set
    private static void SetTileSourceCallback(object sender, 
      DependencyPropertyChangedEventArgs args)
    {
      var map = sender as Map;
      var newSource = args.NewValue as TileSource;
      if (newSource == null || map == null) return;

      // Remove existing layer(s)
      for (var i = map.Children.Count - 1; i &amp;gt;= 0; i--)
      {
        var tileLayer = map.Children[i] as MapTileLayer;
        if (tileLayer != null)
        {
          map.Children.RemoveAt(i);
        }
      }
      
      var newLayer = new MapTileLayer();
      newLayer.TileSources.Add(newSource);
      map.Children.Add(newLayer);
    }
    #endregion
  }
}&lt;/pre&gt;

&lt;p&gt;This quite adequately shows why an attached dependency property is necessary: a Bing Maps controls has Children that can contain (among others) MapTileLayer objects – and only &lt;em&gt;that &lt;/em&gt;contains a TileSource. So when the displayed map is changed, first all current MapTileLayer objects need to be deleted, before a new MapTileLayer containing the new Tilesource is created, that can be added to the Children of the map. With this in place, the whole ViewModel can be databound to the Bing Maps Control. Unfortunately not with Blend, so this will have to go manually, in XAML. Add the namespace in which the BindingHelper class is situated to the namespace declarations at the top of the PhoneApplicationPage:&lt;/p&gt;

&lt;pre&gt;xmlns:MapBindingDemo_ViewModel=&amp;quot;clr-namespace:MapBindingDemo.ViewModel&amp;quot;&lt;/pre&gt;

&lt;p&gt;Now the actual binding to the map needs to take place. On the same spot where ZoomLevel and MapCenter were bound the attached dependency property is bound: &lt;/p&gt;

&lt;pre&gt;&amp;lt;Microsoft_Phone_Controls_Maps:Map x:Name=&amp;quot;Map&amp;quot; Grid.Row=&amp;quot;1&amp;quot; Grid.ColumnSpan=&amp;quot;3&amp;quot;             
  CredentialsProvider=&amp;quot;your_credentials_here&amp;quot; 
  Center=&amp;quot;{Binding MapCenter, Mode=TwoWay}&amp;quot; 
  ZoomLevel=&amp;quot;{Binding ZoomLevel, Mode=TwoWay}&amp;quot; 
  MapBindingDemo_ViewModel:BindingHelpers.TileSource =&amp;quot;{Binding CurrentMap}&amp;quot;&amp;gt;&lt;/pre&gt;

&lt;p&gt;Now the application is fully functional, even in design mode it shows the default map (Bing Aerial). The buttons left and right of the map name change the map that’s displayed – &lt;em&gt;with not a single line of code in the code behind&lt;/em&gt;. Granted, the user experience and look and feel could benefit from some more attention, but nevertheless – mission accomplished. Well, almost. Zoom in a little, select a map that not the default, hit the start button and then hit back. Alas – the default map again, with full world view. The application’s last state is not preserved,&amp;#160; or to put things differently – it does not support tombstoning.&lt;/p&gt;

&lt;p&gt;&lt;font size="4"&gt;Tombstoning an MVVMLight application&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;Mike Talbot has written a brilliant post in which he describes a helper object called “SilverlightSerializer”. This object can serialize virtually every Silverlight and Windows Phone 7 object as a binary. The fun part is that it even serializes non-serializable objects – like MVVMLight’s ViewModelBase. The blog post is called &lt;a href="http://whydoidoit.com/2010/04/08/silverlight-serialization/" target="_blank"&gt;“Silverlight Binary Serialization”&lt;/a&gt; and includes the source code.&lt;/p&gt;

&lt;p&gt;SilverlightSerializer is added to a folder “Serialization” in the project. In the same folder (and namespace) a file “ApplicationExtensions.cs” is added that implements two extension methods on the Application class: one for writing the entire ViewModel to Isolated Storage, and one for reading it back from IS.&lt;/p&gt;

&lt;pre&gt;using System;
using System.IO;
using System.IO.IsolatedStorage;
using System.Windows;
using GalaSoft.MvvmLight;

namespace MapBindingDemo.Serialization
{
  /// &amp;lt;summary&amp;gt;
  /// Some extensions method that allow serializing and deserializing
  /// a model to isolated storage
  /// &amp;lt;/summary&amp;gt;
  public static class ApplicationExtensions
  {
    private static string GetDataFileName( Type t)
    {
      return string.Concat(t.Name, &amp;quot;.dat&amp;quot;);
    }

    public static T RetrieveFromIsolatedStorage&amp;lt;T&amp;gt;(this Application app) 
      where T : class
    {
      using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
      {
        var dataFileName = GetDataFileName(typeof(T));
        if (appStorage.FileExists(dataFileName))
        {
          using (var iss = appStorage.OpenFile(dataFileName, FileMode.Open))
          {
            try
            {
              return SilverlightSerializer.Deserialize(iss) as T;
            }
            catch (Exception e)
            {
              System.Diagnostics.Debug.WriteLine(e);
            }
          }
        }
      }
      return null;
    }

    public static void SaveToIsolatedStorage(this Application app, 
      ViewModelBase model)
    {
      var dataFileName = GetDataFileName((model.GetType()));
      using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
      {
        if (appStorage.FileExists(dataFileName))
        {
          appStorage.DeleteFile(dataFileName);
        }
        using (var iss = appStorage.CreateFile(dataFileName))
        {
           SilverlightSerializer.Serialize(model,iss);          
        }
      }
    }
  }
}&lt;/pre&gt;

&lt;p&gt;These methods are used from App.Xaml’s code behind. This may look like a deviation from the MVVM paradigm, but it’s not as bad as it looks. This file has some default code anyway (the Application_* methods), for this is the place that sports the methods that are called when the application (re)starts or stops. This last step just adds a little code. First, add two usings:&lt;/p&gt;

&lt;pre&gt;using MapBindingDemo.Serialization;
using MapBindingDemo.ViewModel;&lt;/pre&gt;

&lt;p&gt;Then, adapt the existing code till it looks like this:&lt;/p&gt;

&lt;pre&gt;// Code to execute when the application is launching (eg, from Start)
// This code will not execute when the application is reactivated
private void Application_Launching(object sender, LaunchingEventArgs e)
{  
  LoadModelFromIsolatedStorage();
}

// Code to execute when the application is activated (brought to foreground)
// This code will not execute when the application is first launched
private void Application_Activated(object sender, ActivatedEventArgs e)
{
  LoadModelFromIsolatedStorage();
}

/// &lt;summary&gt;
/// Loads the model from isolated storage
/// &lt;/summary&gt;
private void LoadModelFromIsolatedStorage()
{
  MvvmMap.Instance = this.RetrieveFromIsolatedStorage&lt;mvvmmap&gt;();
  if (MvvmMap.Instance == null) MvvmMap.CreateNew();
}

// Code to execute when the application is deactivated (sent to background)
// This code will not execute when the application is closing
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
  this.SaveToIsolatedStorage(MvvmMap.Instance);
}

// Code to execute when the application is closing (eg, user hit Back)
// This code will not execute when the application is deactivated
private void Application_Closing(object sender, ClosingEventArgs e)
{
   this.SaveToIsolatedStorage(MvvmMap.Instance);
}&lt;/pre&gt;

&lt;p&gt;Notice both deactivation and closing call the same code: the data is always written to Isolated Storage. Similarly, launching and deactivation always call RetrieveFromIsolatedStorage. It’s perfectly possible to store the ViewModel in the PhoneApplicationService but then the stored model won’t be available when the application is started again from the start menu (in stead of using the “back” button). This is “works as designed” behavior as far as Windows Phone 7 is concerned but if it’s used in as described above, both the back button and a restart give the same result – the last application state is preserved.&lt;/p&gt;

&lt;p&gt;A drawback of saving the entire ViewModel as a binary is that deserializing fails when major changes are implemented in the ViewModel. This is why it always is surrounded by try/catch statements. Attentive readers also may have noticed that property “AvailableMapSources” is serialized in vain, since it’s always initialized from the constructor. SilverlightSerializer’s default behavior is to serialize everything, but if something needs to be skipped it can be marked with the [DoNotSerialize] attribute defined by SilverlightSerializer itself.&lt;/p&gt;

&lt;p&gt;&lt;font size="4"&gt;Concluding remarks&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;For all but the most trivial Windows Phone 7 applications MVVM simply is the way to go, if only because SilverlightSerializer makes a quite complex thing like tombstoning a breeze. For complex application with multiple models things get a lit more challenging, but it’s clear MVVMLight and SilverlightSerializer are a winning team.&lt;/p&gt;

&lt;p&gt;Thanks to &lt;a href="http://twitter.com/#!/peshir" target="_blank"&gt;Jarno Peshier&lt;/a&gt; and &lt;a href="http://twitter.com/dvroegop" target="_blank"&gt;Dennis Vroegop&lt;/a&gt; for their suggestions on the original article.&lt;/p&gt;

&lt;p&gt;Code can be downloaded &lt;a href="http://www.schaikweb.net/dotnetmag/MapBindingDemo.zip" target="_blank"&gt;here&lt;/a&gt;. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5295746446529817470-1089560454118692103?l=dotnetbyexample.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/dotnetbyexample/~4/_pWooyx8zEc" height="1" width="1"/&gt;</description><atom:updated xmlns:atom="http://www.w3.org/2005/Atom">2011-04-08T12:30:13.721+02:00</atom:updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/_QXPoKuE9q6k/TZ6tFGC8gKI/AAAAAAAAGZw/OHdkRdO9EFk/s72-c/designedapp_thumb.png?imgmax=800" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://dotnetbyexample.blogspot.com/2011/04/bing-maps-control-with-mvvmlight-on.html</feedburner:origLink></item></channel></rss>

