Running a Storyboard as a Task

Sometimes you have some code that needs to run after a storyboard has completed. In my case I'm working on a little board game, and after each move (which I animate using a Storyboard), I need to figure out the next move, and either start a new play-animation or pass the turn to the other player.

Therefore I run in a loop until the turn is over. You can detect when a storyboard has finished when the "Completed" event triggers, but that makes for some recursive spaghetti code. It's much easier if I could just "await" the storyboard using a task. So I created the little extension method below that makes this possible. All you have to do to start and wait for the storyboard to finish is:

    await myStoryboard.BeginAsync();

Below is the little extension method (which also serves as a general example on how you turn an event-based class into an awaitable Task using the TaskCompletionSource):

using System;
using System.Threading.Tasks;
using Windows.UI.Xaml.Media.Animation;

namespace SharpGIS
{
    public static class StoryboardExtensions
    {
        public static Task BeginAsync(this Storyboard storyboard)
        {
            System.Threading.Tasks.TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
            if (storyboard == null)
                tcs.SetException(new ArgumentNullException());
            else
            {
                EventHandler<object> onComplete = null;
                onComplete = (s, e) => {
                    storyboard.Completed -= onComplete; 
                    tcs.SetResult(true); 
                };
                storyboard.Completed += onComplete;
                storyboard.Begin();
            }
            return tcs.Task;
        }
    }
}

Note: This code is written for WinRT. If you want to use this for Silverlight or WPF, just change ‘Eventhandler<object>’ to ‘EventHandler’.

Code snippet for reading files in a Windows Store App

Here’s a little useful code snippet for opening up a file stream from either you local data store, or from the application folder in a Windows Store/WinRT/Metro/[insert name of the day] app:

using System;
using System.IO;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.Storage.Streams;
using System.Runtime.InteropServices.WindowsRuntime;
//[...]
public static async Task<Stream> ReadFile(string filename)
{
    StorageFolder folder = null;
    if (filename.StartsWith("ms-appx:///"))
    {
        filename = filename.Substring(11);
        folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
    }
    else
    {
        folder = Windows.Storage.ApplicationData.Current.LocalFolder;
    }
    while (filename.Contains("/"))
    {
        var foldername = filename.Substring(0, filename.IndexOf('/'));
        filename = filename.Substring(foldername.Length + 1);
        folder = await folder.GetFolderAsync(foldername).AsTask().ConfigureAwait(false);
    }
    var file = await folder.GetFileAsync(filename);
    IInputStream stream = await file.OpenReadAsync();
    DataReader reader = new DataReader(stream);
    return await file.OpenStreamForReadAsync();
}

This allows you to get access to a stream from your application. Ie. if you have a file called “About.txt” in your project inside the folder “Assets” (remember to set build action to ‘content’), you would access it like this:

using (var stream = await ReadFile("ms-appx:///Assets/About.txt"))
{
    //TODO
}

Note that the ms-appx:/// is the standard prefix for a uri to files within the application folder. If you want to get access to a file in your app data folder, just leave this off.

Creating a DirectX XAML control using C++/CX

With Windows 8 Metro style apps, you can now also build XAML controls not only with C# and VB.NET but also with C++. If you are a .NET developer you will probably wonder why you would do that – and granted there might be several reasons you wouldn’t. However there is a few nice things about C++ that .NET libraries doesn’t give you:
1. You can use existing C++ libraries and link them directly in. This will allow you to re-use an enormous amount of code already out there.
2. DirectX is a first-class citizen in C++ 11, and officially the only way to use DirectX in XAML (although there are ways to access this from C#).

If you need high-performance rendering or 3D, DirectX is the way to go on the Windows Platform, and finally we can effortless mix DX and XAML (well at least compared to how it was in WPF). So this blogpost will show you how to build the base control you will need to make DirectX-in-XAML possible.

If you haven’t made any custom controls before, I urge you to read my earlier post on why they are so awesome and how they work: Why Custom Controls are underrated

So let’s open up Visual Studio 11, and go: New Project –> Visual C++ –> WinRT Component DLL

image

The project will create a new component class: WinRTComponent.cpp/.h. Delete these two files. We won’t need them. Instead, right-click project –> Add new item, and pick “Templated Control”.

image

This will add 3 new files, where the first two are:

MyDirectXControl.h:

#pragma once

#include "pch.h"

namespace MyControlsLibrary
{
    public ref class MyDirectXControl sealed : public Windows::UI::Xaml::Controls::Control
    {
    public:
        MyDirectXControl();
    };
}

MyDirectXControl.cpp:

#include "pch.h"
#include "MyDirectXControl.h"

using namespace MyControlsLibrary;

using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Data;
using namespace Windows::UI::Xaml::Documents;
using namespace Windows::UI::Xaml::Input;
using namespace Windows::UI::Xaml::Interop;
using namespace Windows::UI::Xaml::Media;

MyDirectXControl::MyDirectXControl()
{
    DefaultStyleKey = "MyControlsLibrary.MyDirectXControl";
}

Also notice the comment at the top of the header file. This is important, and tells you to go open “pch.h” and add the following line at the bottom:

#include "MyDirectXControl.h"

I ignored this comment (ie. my brain refused to notice it) for hours until a friendly soul pointed it out – kinda annoying but just do it and move along.

The third file is the “Generic.xaml” template file. This is where the XAML that should be applied to the control is defined (this is exactly the same as in C#/VB.NET). We will open this and add a couple of minor changes highlighted in yellow, and remove the line crossed out:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MyControlsLibrary">

    <Style TargetType="local:MyDirectXControl">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:MyDirectXControl">
                    <Border x:Name="DrawSurface"
                        Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                        <TextBlock Text="My DirectX Control" 
                                   HorizontalAlignment="Center"
                                   VerticalAlignment="Center" />
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

We name the border so we can get a reference to it from code behind (which we will get back to later), and also add a little text in the center just for fun.

Next let’s try and use this control in a C# app. Right-click on your solution and select Add New Project. Pick a blank C# Metro style application.

image

Right-click the “references” in this new project and select “Add references” and select your other project under the “Solutions” tab:

image

Now open BlankPage.xaml and add the highlighted sections:

<Page
    x:Class="Application1.BlankPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Application1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:my="using:MyControlsLibrary"
    mc:Ignorable="d">

    <Grid Background="{StaticResource ApplicationPageBackgroundBrush}">
        
        <my:MyDirectXControl Background="Red" Width="400" Height="300" />
        
    </Grid>
</Page>

And you should see the control pop up in your designer (you won’t see the red color yet – I left it so you can better see it in this screenshot):

image

Awesome! We now got a XAML control built in C++ consumed by C#!
Now let’s continue and add some DirectX magic to this control…

The first step for this is to include the DirectX libraries. If you are a .net developer, it’s kinda like adding assembly references (but the experience will feel 1980s :-). Right-click your C++ project and select Properties. Navigate to Linker->Input, and add the following to “Additional Dependencies”: d2d1.lib;d3d11.lib;

image

Next, lets add some methods, overrides and private variables to MyDirectXControl.h file that we’ll be using for the our directx rendering:

#pragma once
#include <d3d11_1.h>
#include <dxgi1_2.h>
#include <wrl.h>
#include <windows.ui.xaml.media.dxinterop.h>

#include "pch.h"

namespace MyControlsLibrary
{
    public ref class MyDirectXControl sealed : public Windows::UI::Xaml::Controls::Control
    {
    public:
        MyDirectXControl();
        virtual void OnApplyTemplate() override;
        void Refresh();

    private:
        Windows::UI::Xaml::Media::Imaging::SurfaceImageSource^ CreateImageSource(int width, int height);
        void OnMapSurfaceSizeChanged(Platform::Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e);
        void Draw(int width, int height);

        // template child that holds the UI Element
        Windows::UI::Xaml::Controls::Border^                m_MapSurfaceElement;
        // surface image source
        Windows::UI::Xaml::Media::Imaging::SurfaceImageSource^ m_imageSource;
        // Native interface of the surface image source
        Microsoft::WRL::ComPtr<ISurfaceImageSourceNative>   m_imageSourceNative;
        // D3D device
        Microsoft::WRL::ComPtr<ID3D11Device>                m_d3dDevice;
        Microsoft::WRL::ComPtr<ID3D11DeviceContext>         m_d3dContext;
Windows::Foundation::EventRegistrationToken m_sizeChangedToken; }; }

The first we’ll implement is the “CreateImageSource” method which will generate a DirectX surface we can render to. We’ll be using SurfaceImageSource which is one of the 3 types of DirectX surfaces we can use for this:

using namespace Windows::UI::Xaml::Media::Imaging;
[...]
SurfaceImageSource^ MyDirectXControl::CreateImageSource(int width, int height)
{
    //Define the size of the shared surface by passing the height and width to 
    //the SurfaceImageSource constructor. You can also indicate whether the surface
    //needs alpha (opacity) support.
    SurfaceImageSource^  surfaceImageSource = ref new SurfaceImageSource(width, height, true);
    if(width <= 0 || height <= 0) return surfaceImageSource;
    

    //Get a pointer to ISurfaceImageSourceNative. Cast the SurfaceImageSource object
    //as IInspectable (or IUnknown), and call QueryInterface on it to get the underlying
    //ISurfaceImageSourceNative implementation. You use the methods defined on this 
    //implementation to set the device and run the draw operations.
    IInspectable* sisInspectable = (IInspectable*) reinterpret_cast<IInspectable*>(surfaceImageSource);
    sisInspectable->QueryInterface(__uuidof(ISurfaceImageSourceNative), (void **)&m_imageSourceNative);

    //Set the DXGI device by first calling D3D11CreateDevice and then passing the device and 
    //context to ISurfaceImageSourceNative::SetDevice. 

    // This flag adds support for surfaces with a different color channel ordering than the API default.
    // It is recommended usage, and is required for compatibility with Direct2D.
    UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;

#if defined(_DEBUG)
    // If the project is in a debug build, enable debugging via SDK Layers with this flag.
    creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
     // This array defines the set of DirectX hardware feature levels this app will support.
    // Note the ordering should be preserved.
    D3D_FEATURE_LEVEL featureLevels[] = 
    {
        D3D_FEATURE_LEVEL_11_1,
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0,
        D3D_FEATURE_LEVEL_9_3,
        D3D_FEATURE_LEVEL_9_2,
        D3D_FEATURE_LEVEL_9_1
    };

    HRESULT hr = D3D11CreateDevice(
            NULL,
            D3D_DRIVER_TYPE_HARDWARE,
            NULL,
            creationFlags,
            featureLevels,
            ARRAYSIZE(featureLevels),
            D3D11_SDK_VERSION,
            &m_d3dDevice,
            NULL,
            &m_d3dContext
            );
if(FAILED(hr))
throw ref new COMException(hr); Microsoft::WRL::ComPtr<IDXGIDevice> dxgiDevice; // Obtain the underlying DXGI device of the Direct3D11.1 device. m_d3dDevice.As(&dxgiDevice); m_imageSourceNative->SetDevice(dxgiDevice.Get()); return surfaceImageSource; }

This is all boiler-plate code from MSDN. You can find more information there about what the above code really do.

The next portion is the code that will actually do the draw. I’ll keep it simple here and just grab the background color of the control, and render that color to the surface.

using namespace Microsoft::WRL;
[...]
void MyDirectXControl::Draw(int width, int height)
{
    if(width <= 0 ||  height <= 0) return;
    ComPtr<IDXGISurface> surface;
    RECT updateRect = {0};
    updateRect.left = 0;
    updateRect.right = width;
    updateRect.top = 0;
    updateRect.bottom = height;
    POINT offset = {0};
    
    //Provide a pointer to IDXGISurface object to ISurfaceImageSourceNative::BeginDraw, and 
    //draw into that surface using DirectX. Only the area specified for update in the 
    //updateRect parameter is drawn. 
    //
    //This method returns the point (x,y) offset of the updated target rectangle in the offset
    //parameter. You use this offset to determine where to draw into inside the IDXGISurface.
    HRESULT beginDrawHR = m_imageSourceNative->BeginDraw(updateRect, &surface, &offset);
    if (beginDrawHR == DXGI_ERROR_DEVICE_REMOVED || beginDrawHR == DXGI_ERROR_DEVICE_RESET)
    {
              // device changed
    }
    else
    {
        // draw to IDXGISurface (the surface paramater)
        // get D3D texture from surface returned by BeginDraw
        ComPtr<ID3D11Texture2D> d3DTexture;
        surface.As(&d3DTexture);
        // create render target view
        ComPtr<ID3D11RenderTargetView> m_renderTargetView;
        m_d3dDevice->CreateRenderTargetView(d3DTexture.Get(), nullptr, &m_renderTargetView);
        auto brush = (SolidColorBrush^)this->Background;
        float a = brush->Color.A/255.0f;
        float r = brush->Color.R/255.0f;
        float g = brush->Color.G/255.0f;
        float b = brush->Color.B/255.0f;
         const float clearColor[4] = { r, g, b, a };
         m_d3dContext->ClearRenderTargetView(m_renderTargetView.Get(),clearColor);
    }

    // TODO: Add more draw calls here

    //Call ISurfaceImageSourceNative::EndDraw to complete the bitmap. Pass this bitmap to an ImageBrush.
    m_imageSourceNative->EndDraw();
}

The next thing we’ll implement is “OnApplyTemplate”, which is called when the template in Generic.xaml is applied. At this point we can get a reference to the Border element, and apply the SurfaceImageSource as a brush to the background of the border.

void MyDirectXControl::OnApplyTemplate() 
{
if(m_MapSurfaceElement != nullptr)
    {   
        m_MapSurfaceElement->SizeChanged -= m_sizeChangedToken;
        m_MapSurfaceElement = nullptr;
    }
    //Get template child for draw surface
    m_MapSurfaceElement = (Border^)GetTemplateChild("DrawSurface");
    if(m_MapSurfaceElement != nullptr)
    {
        int width = (int)m_MapSurfaceElement->ActualWidth;
        int height = (int)m_MapSurfaceElement->ActualHeight;
        m_imageSource = CreateImageSource(width, height);
        ImageBrush^ brush = ref new ImageBrush();
        brush->ImageSource = m_imageSource;
        m_MapSurfaceElement->Background = brush;
        m_sizeChangedToken = m_MapSurfaceElement->SizeChanged += 
ref new SizeChangedEventHandler(this, &MyDirectXControl::OnMapSurfaceSizeChanged); } }

Also notice that we attached a handler to when the border element changes its size. If this happen we need to recreate the surface and render it again:

//surface size changed handler
void MyDirectXControl::OnMapSurfaceSizeChanged(Platform::Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e)
{
    int width = (int)m_MapSurfaceElement->ActualWidth;
    int height = (int)m_MapSurfaceElement->ActualHeight;
    m_imageSource = CreateImageSource(width, height);
    Draw(width, height);
    ImageBrush^ brush = ref new ImageBrush();
    brush->ImageSource = m_imageSource;
    m_MapSurfaceElement->Background = brush;
}

Lastly, we have a Refresh() method that triggers a new draw. You can call this on your control to trigger a new rendering. Calls to should be triggered by a pulse and only happen when there’s something new to draw (like for instance changing the background brush).

void MyDirectXControl::Refresh()
{
    int width = (int)m_MapSurfaceElement->ActualWidth;
    int height = (int)m_MapSurfaceElement->ActualHeight;
    Draw(width, height);
}

And that’s it! We now have a complete XAML control that you can use in both your .NET and C++ XAML apps.

You can download the entire sample app here.

Also a big thanks goes out to Jeremiah Morrill for peer-reviewing this blog-post.

TiltEffect for Windows 8 Metro XAML

The tiles on the new Windows 8 Start Menu “tilts” when you press them, tilting toward the direction you click/touch them. This effect is also well known from the Windows Phone tiles. Unfortunately there is no out-of-the-box way of accomplishing this in either of the platforms. However for Windows Phone, a TiltEffect class is in the Silverlight Toolkit, so I figured I could just port that. Turns out it wasn’t that hard – all I pretty much had to do was change the manipulation events to use the new Pointer events instead, and will work with both mouse and touch.

To use it, first download the updated tilt effect class and add it to your project.

Next add a xmlns to register the namespace for use in XAML:

     xmlns:sg="using:SharpGIS.Metro.Controls"

And lastly add the tilt effect to your control exactly like  you would on the phone:

    <Rectangle Width="200" Height="200" Fill="Blue"
        sg:TiltEffect.IsTiltEnabled="True" />

Here’s what this look like on a couple of animated panels:

It’s worth noting that the tilt effect is not EXACTLY the same as the Windows 8 start menu, but it’s fairly close (and a bit cooler if you ask me Smile)

Why Custom Controls are underrated

I’m a big fan of building controls. I love writing them, designing them, trying to make it work in as many scenarios I can while keeping them simple, extensible and most importantly reusable. In fact for the past 6 years, it’s all I’ve been doing full time (first ASP.NET and later XAML), and frequently in my spare time as well.

If you dabble in XAML, you have most likely already been building some controls, by going “File -> New -> User Control” in Visual Studio. You probably do this because you want to create a new page in your app, or you just want to encapsulate some of the UI in a separate section. Or perhaps it’s because you realize that this little tidbit can be used over and over again in your application. Or maybe you have even considered it can be used again and again across many DIFFERENT applications. If you have tried those two last categories (or if you will one day), this blog post is for you! It will apply to any of the XAML techs there is: WPF, Silverlight, Windows Phone and the future Windows 8 Runtime.

Despite the title in this blog post, User Controls are awesome. They are quick to throw together and reuse over and over - and there’s a lot of value in that. But what if I told you there’s another control type that has even MORE power, better performance, and can be way more flexible and reusable than a user control, and where the clean code will make most developers fall in love?

The thing is you already know this because you’ve been using them all the time: Button, ListBox, ItemsControls, Grid, StackPanel etc. are all controls harnessing the same power you can! And you have probably seen XAML styles that completely changed the look and feel of a control, without touching any of its code. To give you an idea of how powerful this is, look at this Silverlight Sample below. On the left you will see a ListBox binding to a list of planets. You have probably already done something like this. On the right, you see a solar system. But in fact this is ALSO a ListBox. And there is NO extra code involved here. It’s done entirely by restyling the template. Notice how selection and up/down keys work just like it does with the “normal” ListBox. So I got to reuse all the code that has this, and all I had to do was restyle the ListBox a bit. Something I could have done entirely in Blend without ever touching code.

Let me repeat that: I didn’t add any code to the ListBox do this. In fact the code behind for this page is completely empty. If you don’t believe me, here’s the source code. You can also see more about this technique in this presentation from Mix’08, or read David Ansons blogpost on it.

So at this point hopefully I have won you over to learning more about Custom Controls (if not I’m amazed you have read this far :-).

The Anatomy of A User Control

To start, let’s first look at the anatomy of a typical UserControl and try and fully understand how that works first. Below here we have the XAML portion of our control that defines the layout. We’ll keep it simple and have a Grid with a Button inside it:

<UserControl x:Class="MyApp.SilverlightControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    
    <Grid x:Name="LayoutRoot" Background="White">
        <Button Content="Click Me" Click="Button_Click" Opacity=".5" />
    </Grid>
</UserControl>

And we have the code-behind that loads up the control, handles user interaction etc.

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace SolarSystemRetemplate
{
    public partial class SilverlightControl1 : UserControl
    {
        public SilverlightControl1()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            LayoutRoot.Background = new SolidColorBrush(Colors.Red);
        }
    }
}

The things worth noting here are two things: “LayoutRoot” is defined in the XAML using x:Name, and we automatically get a variable by that name in code behind. Also the event handler hooked to the Button’s Click event is magically linked to the code-behind. All this is really handled by the compiler and the “InitializeComponent” call - a method that interestingly doesn’t exist here. The reason this works is really because this is a partial class as indicated, and Visual Studio creates a little ‘secret’ file under the covers for you. You can get to if if you right-click the method and select “Go To Definition”. Here’s what the contents of that file looks like:

namespace MyApp {    
    
    public partial class SilverlightControl1 : System.Windows.Controls.UserControl {
        
        internal System.Windows.Controls.Grid LayoutRoot;
        
        private bool _contentLoaded;
        
        /// <summary>
        /// InitializeComponent
        /// </summary>
        [System.Diagnostics.DebuggerNonUserCodeAttribute()]
        public void InitializeComponent() {
            if (_contentLoaded)
                return;
            _contentLoaded = true;
            System.Windows.Application.LoadComponent(this, 
new System.Uri("/MyApp;component/SilverlightControl1.xaml",
System.UriKind.Relative)); this.LayoutRoot = ((System.Windows.Controls.Grid)(this.FindName("LayoutRoot"))); } } }

You’ll notice that the LayoutRoot is defined here as internal, and it’s assigned using the “FindName” method.

This is one of the nice things about UserControls: A lot of the work is automatically done for you, but with Custom Controls you will have to do this yourself! (but this isn’t so bad considering the power you get!). And here’s the kicker: A UserControl is just another custom control!

The Anatomy of A Custom Control

A custom control doesn’t have a XAML and a code-behind component in the same way UserControl does. Instead it’s ALL code along with a default XAML template. You can consider the template the equivalent of the XAML in the User Control, but the important part to remember here is that this template can be changed by ANYONE, which is what I did to the ListBox in the solar system sample. Another thing to note is that since the template doesn’t have a corresponding code-behind where Visual Studio generates a partial class for you, any event handlers cannot be defined in the template. So how do we go about recreating the user control above as a custom control?

For Silverlight this is easy. Right-click your project and select “File -> Add New -> Silverlight Templated Control”. WPF and Windows Phone doesn’t come with this template so you’ll have to do it manually there, by creating a class and a generic template file. After you do this, you’ll notice two new files: First a simple C# class, and second a new file in \Themes\Generic.xaml. The second file is where you place all templates for all your controls in that assembly. It HAS to have this name and live in this folder for the custom control to pick up the template.

Below is what this template looks like. I’ve added the grid and the button inside the suggested border that was created for me.

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:MyApp">

    <Style TargetType="local:TemplatedControl1">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:TemplatedControl1">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">
                        <Grid x:Name="LayoutRoot">
                            <Button x:Name="ClickButton" Content="Click me!" Opacity=".5" />
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

First notice the TemplateBinding statements on the border. This is an important feature of controls. You can bind straight to a dependency property defined in your control code. Since a custom control inherits from “Control”, you automatically get Background, BorderBrush, BorderThickness and many other general properties from the inheritance. The great thing is that you can just write <my:TemplatedControl Border=”Red” /> and the border will automatically be bound into this template (and anywhere else where you have a TemplateBinding to that property). This beats UserControl, where to accomplish this in Silverlight you will have resolve to a hack by setting the DataContext of the control to itself, breaking the DataContext flow.

Second, notice that I didn’t add a click-handler to Button. If I did, this template would fail to load. We’ll hook the click handler up later.

Next let’s look at the code for the control:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;

namespace MyApp
{
    [TemplatePart(Name="LayoutRoot", Type=typeof(Control))]
    [TemplatePart(Name = "ClickButton", Type = typeof(ButtonBase))]
    public class TemplatedControl1 : Control
    {
        Control layoutRoot;
        ButtonBase button;
        public TemplatedControl1()
        {
            this.DefaultStyleKey = typeof(TemplatedControl1);
        }
        public override void OnApplyTemplate()
        {
            if (button != null) //unhook from previous template part
            {
                button.Click -= new RoutedEventHandler(button_Click);
            }    
            button = GetTemplateChild("ClickButton") as ButtonBase;
            if (button != null)
            {
                button.Click += new RoutedEventHandler(button_Click);
            }
            layoutRoot = GetTemplateChild("LayoutRoot") as Panel;
            base.OnApplyTemplate();
        }

        private void button_Click(object sender, RoutedEventArgs e)
        {
            layoutRoot.Background = new SolidColorBrush(Colors.Red);
        }
    }
}

First I declare the “TemplatePart” attributes on the control. They tell what parts (ie controls) are expected to be in my template. In this case LayoutRoot of type Panel (Grid is a Control), and ClickButton of type ButtonBase. These are not strictly required, but they help Expression Blend understand the template requirements when you later customize the control. I always declare the lowest needed type in the control hierarchy to make the template more flexible. For instance I use ButtonBase and not Button, because I only rely on the Click event which is declared on the ButtonBase base class. That way I don’t lock a user of the control into using “Button” but they can place ANY control that inherits from ButtonBase here. Same thing applies for the LayoutRoot, where I just need the Background property.

Next the control inherits from “Control”. Custom controls must inherit from this.

In the constructor I define the “DefaultStyleKey”. This tells the framework that I have a default template defined in Themes\Generic.xaml. If I didn’t the user would always have to explicitly defined a control template for the control.

Lastly, the most important part is “OnApplyTemplate”. This method is called when the control has loaded the template. This is our earliest opportunity to grab references to controls in the template, ie. the TemplateParts. In this case I grab a reference to the ButtonBase defined in the template. If it’s found, I’ll add a click handler to it. Also if a new template gets applied, I must remember to unhook from the previous instance (this is a rare scenario though, and you could probably get away with skipping that bit). It’s also important to note that Template Parts are always optional! So always do the null check anywhere you rely on a reference to a template part.

And that’s really it! I kept the sample simple, so it is easier to go through the individual parts of a control, therefore the differences between a custom control and a user control doesn’t really stand out. If this was all you needed to do, a custom control is probably overkill. But think of scenarios where you have a lot of code-behind that you want to reuse, but you don’t want to lock the design in. The major next parts you will want to add to this now is more Dependency Properties you can bind into the template, as well as VisualStates - ie. storyboards that triggers on certain events. The great thing about Visual States is that the code-behind doesn’t define the storyboard or what it does - only when it starts. This gives the user even more flexibility to customize the behavior.

Adding Visual States to the control

Let’s add some mouse over states to our control, and have the control animate when that happens. In the code-behind where we defined the TemplateParts let’s add two TemplateVisualState attributes:

[TemplateVisualState(GroupName = "HoverStates", Name = "MouseOver")]
[TemplateVisualState(GroupName = "HoverStates", Name = "Normal")]

Again these are optional, but great for Blend integration.

Next add the code that triggers the visual state to the control:

bool isMouseOver;
protected override void OnMouseEnter(System.Windows.Input.MouseEventArgs e)
{
    isMouseOver = true;
    ChangeVisualState(true);
    base.OnMouseEnter(e);
}
protected override void OnMouseLeave(System.Windows.Input.MouseEventArgs e)
{
    isMouseOver = false;
    ChangeVisualState(true);
    base.OnMouseLeave(e);
}

private void ChangeVisualState(bool useTransitions)
{
    if (isMouseOver)
    {
        GoToState(useTransitions, "MouseOver");
    }
    else
    {
        GoToState(useTransitions, "Normal");
    }
}

private bool GoToState(bool useTransitions, string stateName)
{
    return VisualStateManager.GoToState(this, stateName, useTransitions);
}

This is really all the code we need. It’s pretty simple. If the mouse is over, trigger the MouseOver state, else trigger the Normal state. Note how we don’t really define what “MouseOver” looks like. That’s the job of the template. Let’s define that (you might already be very familiar with this when overriding templates - it’s exactly the same thing, except we get to define the default state):

<ControlTemplate TargetType="local:TemplatedControl1">
    <Border Background="{TemplateBinding Background}"
            BorderBrush="{TemplateBinding BorderBrush}"
            BorderThickness="{TemplateBinding BorderThickness}">
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="HoverStates">
                <VisualState x:Name="MouseOver">
                    <Storyboard>
                        <ColorAnimation
                            Storyboard.TargetName="BackgroundElement"
                            Storyboard.TargetProperty="(Rectangle.Fill).(SolidColorBrush.Color)"
                            To="Yellow" Duration="0:0:.5" />
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="Normal">
                    <Storyboard>
                        <ColorAnimation
                            Storyboard.TargetName="BackgroundElement"
                            Storyboard.TargetProperty="(Rectangle.Fill).(SolidColorBrush.Color)"
                            To="Transparent" Duration="0:0:.5" />
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <Grid x:Name="LayoutRoot">
            <Rectangle x:Name="BackgroundElement" Fill="Transparent" />
            <Button x:Name="ClickButton" 
                    Content="Click me!" Opacity=".5" />
        </Grid>
    </Border>
</ControlTemplate>

So the changes here is adding a rectangle in the background that we animate into yellow when the mouse hovers over.

You now have a control that sets a background on some Panel when some ButtonBase is clicked, as well as running an animation on MouseEnter/Leave. This could serve the purpose for quite a lot of controls, without you having to rewrite the code!

Here’s a few resources you will want to read if you want to learn more about this:

A couple of other controls I’ve built over the time and described on this blog:

If you want to go even more hardcore, wrap your head around the ArrangeOverride and MeasureOverride methods. This is where you can get some really amazing control over how the contents are laid out, but this is outside the scope of this article, but I urge you to read into it. Here’s one article to get your started on that: http://www.switchonthecode.com/tutorials/wpf-tutorial-creating-a-custom-panel-control

Reading and Writing text files in Windows 8 Metro

Perhaps I’m missing something here, but writing a simple text file and reading it back in is surprisingly complex in Windows 8 Metro style apps/WinRT. In .NET there’s a one-liner for such a trivial task, but I haven’t been able to find anything like that in WinRT. So to save you the trouble, here’s my utility methods for this:

Reading a file from the ApplicationData LocalFolder\DataCache:

public static async Task<string> ReadFile(string filename)
{
    var localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
    var folder = await localFolder.GetFolderAsync("DataCache");
    var file = await folder.GetFileAsync(filename);
    var fs = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
    var inStream = fs.GetInputStreamAt(0);
    Windows.Storage.Streams.DataReader reader = new Windows.Storage.Streams.DataReader(inStream);
    await reader.LoadAsync((uint)fs.Size);
    string data = reader.ReadString((uint)fs.Size);
    reader.DetachStream();
    return data;
}

Writing to a file in the ApplicationData LocalFolder\DataCache:

public static async void WriteFile(string filename, string contents)
{
    var localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
    var folder = await localFolder.CreateFolderAsync("DataCache", Windows.Storage.CreationCollisionOption.OpenIfExists);
    var file = await folder.CreateFileAsync(filename, Windows.Storage.CreationCollisionOption.ReplaceExisting);
    var fs = await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);
    var outStream = fs.GetOutputStreamAt(0);
    var dataWriter = new Windows.Storage.Streams.DataWriter(outStream);
    dataWriter.WriteString(contents);
    await dataWriter.StoreAsync();
    dataWriter.DetachStream();
    await outStream.FlushAsync();
}

I used this to create a little data cacher , as shown below (Note: you could use the LocalSettings for this, but there’s a very low limit to how large objects stored there can be):

public static void SaveData(string filename, object objectGraph, bool overwriteIfNull = true)
{
    string json = null;
    if(objectGraph != null)
        json = SerializeObjectGraph(objectGraph);
    if (json != null || overwriteIfNull)
    {
        WriteFile(filename, json);
    }
}

private static string SerializeObjectGraph(object graph)
{
    if (graph == null) return null;
    DataContractJsonSerializer ser = new DataContractJsonSerializer(graph.GetType());
    MemoryStream ms = new MemoryStream();
    ser.WriteObject(ms, graph);
    var bytes = ms.ToArray();
    return UTF8Encoding.UTF8.GetString(bytes, 0, bytes.Length);
}

public static async Task<T> LoadData<T>(string filename)
{
    var json = await ReadFile(filename);
    MemoryStream ms = new MemoryStream(UTF8Encoding.UTF8.GetBytes(json));
    DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
    T result = (T)ser.ReadObject(ms);
    return result;
}

If there’s an easier way to do this, please do let me know. If not, hopefully we’ll get some more utility/helper methods as the SDK matures.

UPDATE: Turns out that there is an easier way to do this after all using the Windows.Storage.PathIO class!

Reading a text file in one line of code using WinRT:

string contents = await Windows.Storage.PathIO.ReadTextAsync("ms-appdata:///local/DataCache/test.txt");

Opening a managed stream using a path:

using (var stream = await Windows.Storage.ApplicationData.Current.LocalFolder.OpenStreamForReadAsync("DataCache\\test.txt"))
    using (var streamReader = new StreamReader(stream))
        contents = streamReader.ReadToEnd();

Similarly Windows.Storage.PathIO also have other neat one-liners. Check out the reference here: http://msdn.microsoft.com/en-us/library/windows/apps/windows.storage.pathio.aspx

Notice that there is also a WriteTextAsync(string,string) method. However this seems to throw an exception if the file doesn’t already exist, so I’m not sure how useful that is at this point, considering this will be a-chicken-and-the-egg scenario. So for now, the code above is still useful for writing files, and of course also for understanding the more low-level file operations.

Make your Windows 8 Video App use the PlayTo feature

If you are making a video app for Windows 8 Metro there are 6 lines of code you simply MUST add. The feature you get for such a little effort will make your jaw drop (well at least mine did). Here’s what the experience is like:

Imagine you are watching a video on your Windows 8 PC or Tablet:

image

But watching TV on the PC kinda sucks. So the first thing you do is to swipe from the right to bring out the Windows 8 Charms menu:

2

You hit the “Devices” charm, and voila, all your media clients show up under “Play To”. Now you just pick your PlayTo enabled TV/Device, or even any Windows Media Player running on Win7 or 8:

image

And the next thing you know this happens:

4

Voila! The Christmas cheer is now playing on the TV for everyone to enjoy. And I can continue to use the playback controls on my PC to play, pause, fast forward, rewind etc.

How to accomplish this is described in depth in the “Play To and Media Sharing for Metro Style Apps” white paper. But it’s so simple to set up, that I’ll quickly tell you how.

First thing you do is that to add a MediaElement to your Win8 Metro app page (if you made a video app you already did this):

    <MediaElement x:Name="videoplayer" Source="http://www.contoso.com/clip.mp4" AutoPlay="true" />
When you assign a video source to the media element, simply hook up an event listener to when the user picks a play to device:

// Step 1: Obtain PlayToManager object for app’s current view.
PlayToManager ptm = Windows.Media.PlayTo.PlayToManager.GetForCurrentView();
// Step 2: Register for the SourceRequested event (user selects Devices button).
ptm.SourceRequested += (PlayToManager sender, PlayToSourceRequestedEventArgs e) => {
    request = e.SourceRequest;
    // Step 3: Specify the media to be streamed.
    PlayToSourceDeferral deferral = request.GetDeferral();
    request.SetSource(videoplayer.PlayToSource);
    deferral.Complete();
}
And that’s ALL you need to do! No need to build any UI around this. No need to figure out how to stream various types of video streams (as far as I can tell both local files and remote video streams works with this). And yes this can even be extended to work with images and music as well.

So those 6 lines of code should ALWAYS be in your video player app, and you’ll make a lot of people very happy (Netflix and Hulu are you reading this?).

In the Windows 8 Developer Preview there is a limitation on what devices this works on for now though. From the white paper:

Only the below list of Play To receivers are supported in the Developer Preview. For scenario testing/validation from apps the easiest solution is to use Windows Media Player on another PC on the same Private Network. Other available devices are:
·    WD Live Hub (firmware version: 2.07.17)
·    Onkyo AV Receivers (Windows 7 Certified models)
·    Windows Media Player (on Windows 7 and the Windows Developer Preview)
·    Metro style apps with Play To Receiver functionality

Since Windows Media Player supports this, it’s pretty easy to test for yourself with a second Win7 or 8 PC. Here’s how to configure Windows Media Player as a Play To receiver:

·    Open Windows Media Player and navigate to the Stream menu
·    Select Allow remote control of my Player

image

If both PC’s are on the same private network and have sharing enabled, that’s really all you need to do. Windows 8 will automatically pick it up and add it to the list of Play To devices.

If you have problems making this work, I suggest you first read the white paper, since this also covers known issues and how to correctly configure your devices on your network.

Building an Augmented Reality XAML control

Augmented Reality on Windows Phone and Windows 8 Metro style apps

I’ve lately been playing a lot with augmented reality on my Windows Phone and my Windows 8 Tablet. Both of them feature an accelerometer, compass and gyro as well as a back facing camera. This makes it possible to overlay various XAML elements on top of the camera feed, and have them move with the camera as you rotate and orient the device. As an example of this, you can try the AR view in my GuidePost app for Windows Phone (and while you’re at it, make sure you throw some good reviews in there ;-). The app uses the exact approach described here.

To do augmented reality in XAML, I built a custom panel control that automatically handles the placement of all it’s child elements based on the device’s orientation. I used an attached property to define what ‘direction’ an element is supposed to be placed in. You already know this from Grid and Canvas, where for instance Grid.Row=”1” places it in the second row of the grid, or Canvas.Top=”100” places the element 100 pixels from the top of the canvas. In my case I use ARPanel.Direction to define a Point where the first value is the azimuth (ie up/down) and second value is the compass heading.

Note: Since you probably know the Grid panel very well, to help explain how this custom panel works, you’ll sometimes see a “How Grid uses this” section, to explain how the grid control would do something similar.

Here’s what the four cardinal directions and up and down would look like in such a custom panel that we’ll be building:

<ar:ARPanel>
    <TextBlock Text="North" ar:ARPanel.Direction="0,0" />
    <TextBlock Text="East"  ar:ARPanel.Direction="0,90" />
    <TextBlock Text="South" ar:ARPanel.Direction="0,180" />
    <TextBlock Text="West"  ar:ARPanel.Direction="0,270" />
    <TextBlock Text="Up"    ar:ARPanel.Direction="90,0" />
    <TextBlock Text="Down"  ar:ARPanel.Direction="-90,0" />
</ar:ARPanel>

Neat huh? This makes it VERY simple to spit out a bunch of different AR-type of apps. So how did I build this?

The custom panel

When building a custom panel, there’s really just 3 things you need to do:

  1. Inherit from Panel
  2. Override MeasureOverride
  3. Override ArrangeOverride

Or to put that in code:

public class ARPanel : Panel
{
    protected override Size MeasureOverride(Size availableSize)
    {
        //TODO
    }
    protected override Size ArrangeOverride(Size finalSize)
    {
        //TODO
    }
}

The two methods here have the following purposes:

MeasureOverride is called first, and it should go through all the child elements and tell them “Hey I got this much space available - how much of that do you need?”.

How Grid uses this: If a grid is 150x100 and has two rows and two columns, it would look at the row/column of the element then say “I got this much 75x50 space in this row/column - how much do you want”. If all the row/column sizes are auto, it would send the entire size of the grid itself to the child.

ArrangeOverride is called second. This goes through all the child elements and tells them “I heard you want this much space (as indicated by child.DesiredSize), but I can only give you this much, and this is the area where you get to place yourself”.

How Grid uses this: After going through the measure step, Grid would now determine what the size of each row and column needs to be based on the child desired elements (unless the cell sizes are fixed), and then calculate the rectangle for each cell distributed based on the row/column definitions. These rectangles are then used to place the child elements in the row/column they are set to be placed in.

Now first let’s implement MeasureOverride, since this is very simple in this scenario. Each child element can render itself anywhere around you in a 360 degree space, so we don’t need to limit the child elements to any size other than the size of the panel itself. So we’ll ask each child “Given all of my space, how much would you want to use?”. This is simply done by going through each child element and calling Measure on them with the full size available (after each measure call, you will notice that child.DesiredSize will now be assigned). We end the call by returning the size that the panel needs to it’s parent - in this case we want to use the entire space available to us:

protected override Size MeasureOverride(Size availableSize)
{
    foreach (var child in Children)
        child.Measure(availableSize);
    return availableSize;
}

MeasureOverride is called whenever the panel’s size is changing or anything else that would affect the size of the child elements. You can trigger this yourself by calling panel.InvalidateMeasure(). In our specific case we don’t ever need to call this, and the measure will only get invalidated when the panel’s size changes - for instance when page orientation changes, and luckily this is all done for us. (Grid would call InvalidateMeasure if the row/column definitions change)

Next up is ArrangeOverride. Now that we measured all the elements, we need to determine where to place them on the screen, and how much space we need to give each of them. We’ll basically go through each element and call Arrange(rect) on them, where the ‘rect’ is the rectangle it gets to render itself in. Ie. the top-left corner is where the area starts, and the width/height is the size it gets. It’s then up to the child to make use of that area. In our ARPanel case, the top/left corner would constantly change as the orientation of the device changes, but we’ll keep the width/height to the desired size of the element. So the method will look something like this:

protected override Size ArrangeOverride(Size finalSize)
{
    foreach(var child in Children)
    {
        double centerX = TODO;
double centerY = TODO;
double left = centerX - child.DesiredSize.Width * .5; double top = centerY - child.DesiredSize.Height * .5; Rect rect = new Rect(new Point(left, top), child.DesiredSize); child.Arrange(rect); } }

I subtract half the width/height of the size to center the element on top of ‘centerX’ and ‘centerY’, which we will still have to determine;

So this is basically our panel implementation. The tricky part is figuring out the “TODO” part of the above code based on the motion sensor. So basically, given a device orientation, what is the screen location of a direction?

Warning: I spent quite a lot of time on getting this part right. It’s a lot of vector math, and some of it I came to using pure trial and error :-). Therefore I might not even completely get all of it myself, but it works, and it works great. I’m pretty sure the math is right, but if I don’t go too much into detail in some of the math, just think of it as magic that works and use the code as is :-) For those of you who are used to XNA 3D Game programming, I’m sure this will all make sense to you though, since this is very similar to how you control a camera in a 3D environment.

The motion sensor

The Motion Sensor is what will be driving the placement of the child elements. Motion is a combination of Compass, Accelerometer and optionally Gyro. The Gyro is not required, but it makes the result A LOT better - especially when you rotate the device fast. Future certified Windows 8 tablets will require all 3 sensors, but for Windows Phone, only some of the newer Mango phones has a gyro, and I believe the Dell Venue Pro compass sensor doesn’t work. Future cheaper Windows Phone devices might not come with any sensors available, so beware that your app might not work on all devices, and you should check for the capability and notify the user if it’s missing.

On Windows Phone you can check whether the motion sensor is supported using ‘Microsoft.Devices.Sensors.Motion.IsSupported’. I didn’t find an equivalent property in Windows Runtime though. The following code starts reading from the sensor for both WinPhone and Windows Runtime:

#if WINDOWS_PHONE
    if (Microsoft.Devices.Sensors.Motion.IsSupported)
    {
        motion = new Microsoft.Devices.Sensors.Motion();
        motion.CurrentValueChanged += motion_CurrentValueChanged;
        motion.Start();
#elif WINRT
    motion = Windows.Devices.Sensors.OrientationSensor.GetDefault();
    if (motion != null)
    {
        motion.ReadingChanged += motion_CurrentValueChanged;
#endif
    }
    else
    {
        throw new InvalidOperationException("Motion sensor not supported on this device");
    }
#endif

When we get a new reading, all we have to do is tell the panel, that the current child placements are invalid. We don’t want to do too much work here, because the motion sensor can be triggering much more frequent than the layout cycle, so all we do here is flag the panel for arrange and clear any parameters that could be affected by the orientation change (like the attitude which I will get back to):

    private Matrix? _attitude;

    private void motion_CurrentValueChanged(object sender, EventArgs e)
    {
        _attitude = null;
 #if WINDOWS_PHONE
        Dispatcher.BeginInvoke(() => InvalidateArrange());
#elif WINRT
        Dispatcher.Invoke(Windows.UI.Core.CoreDispatcherPriority.Normal, 
                          (a, b) => InvalidateArrange(), this, null);
#endif
    }

Handling sensor and screen coordinate systems

The Motion sensor gives us a Matrix that defines the rotation of the device relative to up and north directions. The screen has a different coordinate system that is relative to the upper left corner of the screen. When the screen changes between landscape and portrait mode, this coordinate system changes relative to the motion sensors coordinate system, and it’s important to take this into account. Lastly we need to define a field of view for the screen. If you are overlaying elements on top of the camera, the field of view must match the field of view of the camera. Think of it as how ‘narrow’ the view is. A lens that is zoom in far has a small field of view, and only few elements will be visible on the screen, whereas a wide angle lens will have more child elements on the same screen. I found that on my phones a FOV of roughly 35 degrees seems appropriate. So to sum up we need 3 things: The orientation of the sensor, the orientation of the view (screen), and the parameters for the camera (the projection).

First the view, which is slightly different between phone and runtime (probably because the ‘natural’ orientation on a phone is portrait mode, whereas on a PC it’s landscape mode, so the sensors are mounted different).

    Matrix view;
if (orientation == LandscapeLeft) { view = Microsoft.Xna.Framework.Matrix.CreateLookAt( new Microsoft.Xna.Framework.Vector3(0, 0, 1), Vector3.Zero, #if WINDOWS_PHONE Vector3.Right); #elif WINRT Vector3.Up); #endif } else if (orientation == LandscapeRight) { view = Microsoft.Xna.Framework.Matrix.CreateLookAt( new Vector3(0, 0, 1), Vector3.Zero, #if WINDOWS_PHONE Vector3.Left); #elif WINRT Vector3.Down); #endif } else //portrait mode { view = Microsoft.Xna.Framework.Matrix.CreateLookAt( new Vector3(0, 0, 1), Vector3.Zero, #if WINDOWS_PHONE Vector3.Up); #elif WINRT Vector3.Left); #endif

Next we define a viewport based on this view. Note that this depends on the size of the screen, so on size changed we need to remember to reset this value.

private Microsoft.Xna.Framework.Graphics.Viewport? _viewport;
private Microsoft.Xna.Framework.Graphics.Viewport Viewport
{
    get
    {
        if (!_viewport.HasValue)
        {
            _viewport = new Microsoft.Xna.Framework.Graphics.Viewport(0, 0, (int)ActualWidth, (int)ActualHeight);
            _cameraProjection = null; //camera projection depends on viewport - force a reset
        }
        return _viewport.Value;
    }
}

And from this we can now define the projection of the camera / field of view.

private Matrix CameraProjection
{
    get
    {
        if (!_cameraProjection.HasValue)
        {
           _cameraProjection = Matrix.CreatePerspectiveFieldOfView(
MathHelper.ToRadians((float)FieldOfView), Viewport.AspectRatio, 1f, 12f); } return _cameraProjection.Value; } }

Now we need the attitude of the device based on the current sensor reading (this was the value we reset in reading changed event). We rotate this value so it matches the rotation of the XNA coordinate system as well.

    private Matrix Attitude
    {
        get
        {
            if (!_attitude.HasValue)
            {
                if (motion != null 
#if WINDOWS_PHONE
                    && motion.IsDataValid
#endif
                    )
                {
                    _attitude = Matrix.CreateRotationX(MathHelper.PiOver2) * CurrentReading;
                }
                else
                    return Matrix.Identity;
            }
            return _attitude.Value;
        }
    }
#if WINDOWS_PHONE
    private Matrix CurrentReading
#elif WINRT
    private SensorRotationMatrix CurrentReading
#endif
    {
        get
        {
            return
#if WINDOWS_PHONE
                motion.CurrentValue.Attitude.RotationMatrix;
#elif WINRT
                motion.GetCurrentReading().RotationMatrix;
#endif
        }
    }

Ok that’s a lot of funky stuff, but now we are pretty set to project from vectors to screen coordinates using this simple method:

Matrix world = Matrix.CreateWorld(Vector3.Zero, new Vector3(0, 0, -1), new Vector3(0, 1, 0));
// Projects the point from 3D space into screen coordinates.
private Vector3 Project(Vector3 vector)
{
    return Viewport.Project(vector, CameraProjection, view, world * Attitude);
}

Only thing is we have a direction ray and not a vector. A little extra method for converting to a vector is needed too:

private static Vector3 PolarToVector(double px, double py, double radius)
{
    var O = (py - 90) * PI_OVER_180; // / 180d * Math.PI;
    var W = (90 - px) * PI_OVER_180; // / 180d * Math.PI;
    var x = (float)((Math.Cos(O) * Math.Sin(W)) * radius);
    var y = (float)((Math.Cos(W)) * radius);
    var z = (float)((Math.Sin(O) * Math.Sin(W)) * radius);
    return new Vector3(x, y, z);
}

We don’t have any radius, but I found always using a value of ‘10’ (which is 10 units down the ray) works pretty well. So… we are now pretty set to implement the ArrangeOverride method.

Arranging the child elements

When arranging the children, we need to first check if it’s inside the screen view, and next where on the screen that is. I’m using the BoundingFrustum to do this. Think of the bounding frustum as the space the camera can see, and is a cone the expands out from the camera We can set this up using:

    BoundingFrustum viewFrustum = new BoundingFrustum(Attitude * view * CameraProjection);

If we now build a BoundingSphere around each element, we can use the .Contains method to see if that element is within the frustum. So we first grab the Point object from the element, and build a bounding sphere. If it is inside, all we have to do is call the Project method above to get the screen location, and lastly call Arrange on the element.

So our entire ArrangeOverride method ends up looking like this:

    protected override Size ArrangeOverride(Size finalSize)
    {
        if (ActualWidth > 0 && ActualHeight > 0 && motion != null
#if WINDOWS_PHONE
            && motion.IsDataValid
#endif
            )
        {
            BoundingFrustum viewFrustum = new BoundingFrustum(Attitude * view * CameraProjection);
            foreach (var child in Children)
            {
                object posObj = child.GetValue(DirectionProperty);
                if (posObj is Point && !double.IsNaN(((Point)posObj).X))
                {
                    Point p = (Point)posObj;
                    Vector3 direction = PolarToVector(p.X, p.Y, 10);
                    var size = child.DesiredSize;
                    //Create a bounding sphere around the element for hittesting against the current frustum
                    //This size is not entirely right... size we have is screen size but we use the world size. 
                    //*.008 seems to roughly fit as conversion factor for now
                    var box = new BoundingSphere(direction, (float)Math.Max(size.Width, size.Height) * .008f);
                    if (viewFrustum.Contains(box) != ContainmentType.Disjoint) //partially or fully inside camera frustum
                    {
                        Vector3 projected = Project(direction);
                        if (!float.IsNaN(projected.X) && !float.IsNaN(projected.Y))
                        {
                            //Arrange element centered on projected coordinate
                            double x = projected.X - size.Width * .5;
                            double y = projected.Y - size.Height * .5;
                            child.Arrange(new Rect(x, y, size.Width, size.Height));
                            continue;
                        }
                    }
                }
                //if we fall through to here, it's because the element is outside the view,
                //or placement can't be calculated
                child.Arrange(new Rect(0, 0, 0, 0));
            }
            return finalSize;
        }
        else
            return base.ArrangeOverride(finalSize);
    }

Congrats on making it this far - because we are actually pretty much done! All there’s left to do is put it all together, reset the used orientation parameters when needed and define the attached property for use on the child elements. And I already did all that for you!

You can download the control library together with a sample app here. There’s both a Windows Phone and Windows 8 Metro version included. You can use the code as you like, but if you improve on it, I would LOVE to hear about it. I didn’t include a camera background in the samples, so I’ll let that bit be up to you to add (you can use a VideoBrush as the background for that).

Note that for Windows Runtime, I have only tested this on the Samsung Build Tablet. I have no idea how this behaves on a device without a motion sensor (probably crashes, but let me know in the comments below). Also the Build tablets have a buggy fusion sensor firmware, which means that readings are fired VERY infrequent, making it almost useless for anything but rough testing.

Also note that the compass sensor can get very confused when you are inside - especially if the building has a metal frame construction. If directions seem off, try going outside away from anything that confuses the magnetic field.

WinRT vs. Silverlight - Part 8 - What other people are blogging

See intro blogpost here.

Over the last few months several other people have been writing blog posts covering the transition from WPF/Silverlight/WP7 to WinRT. Below are some of the ones I’ve stumbled upon.

Colin Eberhardt - XAMLFinance - A Cross-platform WPF, Silverlight and WP7 Application
An app that reuses code across 3 different XAML platforms and compiles for all of them. A great example that this can be accomplished. Also make sure to check out Colin’s blog for more WinRT goodness.

Jeffrey Richter - Core .NET Type usable from a Metro Styl Application
A list of the “standard” .NET types that are available in WinRT as well.

Andy’s blog - Physics Games: Multi-targeting Windows 8 and Windows Phone 7
Andy goes through building a physics-based game for both Windows 8 and Windows Phone 7. Also check out his Physics Helper library for WinRT.

Tim Greenfield - “WinRT Genome Project”
Visual comparison of how much overlay Silverlight 5 and WinRT has.

Tim Greenfield - Silverlight 5 vs. WinRT comparison
A follow-up to the link above with a comparison of namespaces, members, types and differences between SL5 and WinRT. This is an amazing list if you want to get into the details when reusing code between the two frameworks.

Pontus Wittenmarks’s - 10 tips about porting Silverlight apps to WinRT/Metro style apps (Part 1)
A quick list of of tips when porting from Silverlight to WinRT.

Petzold Book Blog - Windows 8 Dependency Property Strangeness
Talks about some of the issues with Dependency Properties in Windows 8. I already briefly touched on this, but this goes a lot more in-depth.

If I find more, I’ll add them here, or feel free to mention any other good resources in the comments below.

Correctly displaying your current location

With GPS receivers integrated in phones, tablets and PCs, a lot of apps are being built that displays your current location. Usually the GPS API’s that these devices come with provides you with two values: Longitude and Latitude in decimal degrees, and often an estimated accuracy in meters. Most apps just display these values as is, without considering formatting or number of significant digits. This blog post attempts to show how this could be done. I’ll use C# for this, but it should apply to any device, language and API out there.

Formatting

Some people think of longitude as the “X” in an ordinary flat X,Y the coordinate system and latitude as Y/Up/North. It’s technically not correct because this is not a flat coordinate system, but a ‘polar’ coordinate system - I do however understand this simplification and I think of it the same way internally when working with code that deals with any type of coordinate system. However, how things work internally and how they are displayed are two very different things. An example of this are date objects: They are usually stored and handled as a ‘tick’ number, but we never display it like that. Geographical coordinates are the same way. They have one way they are stored in memory, and a completely different way to be displayed.

First of all lets get the order out of the way: If you still think of longitude as the ‘x’ you probably want to display this value first. However it’s commonly agreed upon that latitude is displayed before longitude.

Next are negative coordinates. Instead of showing a latitude/longitude as for instance -117,34 you would write 117°W 34°N. So we prefix the coordinate with N/S and E/W depending on weather the coordinate is positive or negative. So in C# this could look like this:

char ns = lat < 0 ? 'S' : 'N'; //Southern or Northern hemisphere?
char ew = lon < 0 ? 'W' : 'E'; //Eastern or Western hemisphere?
string formatted = string.Format("{0}°{1} , {2}°{3}", Math.Abs(lat), ns, Math.Abs(lon), ew);

Now this is still decimal degrees. A more ‘proper’ format would be to use the degrees, minutes, seconds (DMS) format . Some people do prefer decimal degrees though, so you might want to make this a configurable option. But if you expect people to be using this coordinate to plot a position on a map, you are better off using DMS, since this is the format maps uses along its edge - and it also looks prettier. Degrees are denoted with a °, minutes with a single quote ' and seconds with a double quote ". For example 117°W 23' 12.34”

To make this conversion you will first show the integer part of the degrees. Take the remainder multiply by 60, and you’ll get the minutes. Lastly take the remainder of that and do the same, and you got the seconds (and you can display the seconds with decimals, but see the part on ‘accuracy’ next).  Below is what that will look like in C#:

char ns = lat < 0 ? 'S' : 'N'; //Southern or Northern hemisphere?
char ew = lon < 0 ? 'W' : 'E'; //Eastern or Western hemisphere?
//Make positive
lon = Math.Abs(lon);
lat = Math.Abs(lat);
//Grab the part in front of the decimal
var majorLong = Math.Floor(lon);
var majorLat = Math.Floor(lat);
//the value after the decimal in minutes (*60)
var minorLong = (lon - majorLong) * 60;
var minorLat = (lat - majorLat) * 60;
//Minutes:
var minutesLong = Math.Floor(minorLong);
var minutesLat = Math.Floor(minorLat);
//Seconds:
var secondsLong = (minorLong - minutesLong) * 60;
var secondsLat = (minorLat - minutesLat) * 60;
string formatted = string.Format("{0}{1}°{2}'{3}\" {4}{5}°{6}'{7}\"", ns, majorLat, minutesLat, secondsLat, ew, majorLong, minutesLong, secondsLong);

Accuracy

Often I see a location displayed as for example -117.342817243 , 34.212381313. When I see this many digits I instantly think ‘oooooh that’s a very accurate location’. But this is very misleading. In college, several of our professors would fail our reports if the end result displayed more digits than the accuracy of the input data. The same thing applies here. If your GPS receivers accuracy is 1000m, how many digits should you display, and how many meters is one second?

First a little about the size and shape of earth: While earth is not a perfect sphere, it’s fairly close to an ellipsoid (this is still an approximation though). It’s widest at equator, and smallest (flattened) between the north and south pole. So in ellipsoid-speak the parameters are:

Semi-major axis: 6,378,137m
Semi-minor axis: 6,356,752.3142m
Mean radius (mR): 6,367,449m

So back to the question: How many meters is one second? This is pretty easy to determine for latitude, but unfortunately this is not a straightforward conversion for longitude, since this changes with the latitude. Let’s first start with the simpler latitude:
First we need the circumference of Earth along a meridian (a line that goes north/south) and Equator:

Circumference at Equator: 2 * Pi * 6,378,137 = 40,075,016 m
Circumference of a meridian : 2 * Pi *  6,356,752 = 39,940,652 m

For simplicity let's stick with a rough average of 40mio meters, since this is not going to really matter for the end result.
From that we get:

Horizontal length of one degree at Equator or along a meridian:
     40,000,000 / 360 = 111,111m
Horizontal length of one second at Equator or along a meridian:
    111111.111 / 60 minutes / 60 seconds = 31m

So from that we get that we should never display any decimals on seconds unless our accuracy is better than 31 meters. And we shouldn’t display more than one decimal unless the accuracy is 3m or better (which never happens with standard GPS equipment). Similarly if we are using decimal degrees instead of DMS for display, how much does the n'th digit matter at Equator or along a meridian?

5 digits: 0.000,01 * 40000000 = 400m 
6 digits: 0.000,001 * 40000000 = 40m
7 digits: 0.000,000,1 * 40000000 = 4m

So in this case we will only show 7 digits if accuracy is better than 40m, and probably never more than 7 digits.

Latitude always goes along a meridian, so the number of significant digits doesn't ever change with your location. But the length of one degree at a longitude changes with the latitude you're at.
The radius of a longitude at a given latitude is: cos(latitude)*mR*2*PI.
At 34 north or south that would be: 33,168,021m. So here the number is roughly 3m instead of 4m, meaning you are more likely to show more digits on the longitude portion for the coordinate, the further north you go. In general practice however, this is not going to matter too much, since it only gets better. so to keep it simple we’ll just stick with the same conversion at all latitudes.

Bringing it all together

So let’s bring all this together into a C# ValueConverter you can use for binding against a GeoCoordinate object returned by the GeoCoordinateWatcher in .NET and Windows Phone. A converter parameter is used for choosing whether you want DMS or decimal degrees as output.

using System;
using System.Device.Location;
using System.Globalization;
using System.Windows.Data;

namespace CoordinateDisplay
{
    /// <summary>
    /// Converts a GeoCoordinate to Degrees-Minutes-Seconds
    /// </summary>
    public class CoordinateConverter : IValueConverter
    {
        private const double MeanEarthRadius = 6367449; //meters
        private const double MeanEarthCircumference = 2 * Math.PI * MeanEarthRadius; //meters
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is GeoCoordinate)
            {
                var coord = value as GeoCoordinate;
                if(coord.IsUnknown) return "Unknown";

                double lat = coord.Latitude;
                double lon = coord.Longitude;
                if ((parameter is string) &&
                    string.Compare("decimal", parameter as string, StringComparison.OrdinalIgnoreCase) == 0)
                //show as decimal degrees
                {
                    var decimalsLat = 7;
                    var decimalsLon = 7;
                    int val = 4;
                    if (coord.HorizontalAccuracy > val * 100) decimalsLat = 5;
                    else if (coord.HorizontalAccuracy > val * 10) decimalsLat = 6;
                    val = (int)Math.Floor(Math.Cos(lat / 180 * Math.PI) * MeanEarthCircumference / 10000000d);
                    if (coord.HorizontalAccuracy > val * 100) decimalsLon = 5;
                    else if (coord.HorizontalAccuracy > val * 10) decimalsLon = 6;
                    return string.Format("{0}°,{1}°", Math.Round(lat, decimalsLat), Math.Round(lon, decimalsLon));
                }
                else //Show as degrees/minutes/seconds
                {
                    char ns = lat < 0 ? 'S' : 'N'; //Southern or Northern hemisphere?
                    char ew = lon < 0 ? 'W' : 'E'; //Eastern or Western hemisphere?
                    //Make positive
                    lon = Math.Abs(lon);
                    lat = Math.Abs(lat);
                    //Grab the part in front of the decimal
                    var majorLong = Math.Floor(lon);
                    var majorLat = Math.Floor(lat);
                    //the value after the decimal in minutes (*60)
                    var minorLong = (lon - majorLong) * 60;
                    var minorLat = (lat - majorLat) * 60;
                    //Seconds:
                    var minutesLong = Math.Floor(minorLong);
                    var minutesLat = Math.Floor(minorLat);

                    //one digit accuracy on one second equals ~3m or better
                    //this changes with the latitude, but this is good enough for now
                    int decimals = 1;
                    if (coord.HorizontalAccuracy > 30)
                        decimals = 0; //With this accuracy we don't need to show sub-second accuracy
                    //Seconds:
                    var secondsLong = Math.Round((minorLong - minutesLong) * 60, decimals);
                    var secondsLat = Math.Round((minorLat - minutesLat) * 60, decimals);
                    return string.Format("{0}{1}°{2}'{3}\" {4}{5}°{6}'{7}\"",
                        ns, majorLat, minutesLat, secondsLat,
                        ew, majorLong, minutesLong, secondsLong);
                }
            }
            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }
}

Here’s an example of using that in XAML where the datacontext is the GeoCoordinate:

<Grid>
    <Grid.Resources>
        <local:CoordinateConverter x:Name="dmsConverter" />
    </Grid.Resources>
    <StackPanel>
        <TextBlock Text="Degrees minutes seconds:" />
        <TextBlock Text="{Binding Converter={StaticResource dmsConverter}}" />
        <TextBlock Text="Decimal degrees:" />
        <TextBlock Text="{Binding Converter={StaticResource dmsConverter}, ConverterParameter=decimal}" />
        <TextBlock Text="{Binding Path=HorizontalAccuracy, StringFormat=Accuracy: \{0:0\}m}" />
    </StackPanel>
</Grid>

And what this can look like on a Windows Phone with different accuracies (notice the different number of digits):

imageimage

You can download this sample app here.