Building custom XAML control panels

One of my favorite XAML Control primitives is the Panel class. It's what drives Grid, StackPanel, Canvas and many many other controls that contains a set of other controls, and controls layout the children out in the view.

So in my second twitch stream, I walked through creating a custom panel that lays out controls in a grid-like manner, without having to do all the row and column definitions. It mainly focuses on the Arrange and Measure steps in the layout life-cycle, which applies to both WPF, UWP and WinUI (or even Silverlight for that matter ;-). And just for fun I used the latest WinUI 3.0 Alpha release (but it really doesn't matter as the concepts are the exact same - only namespaces differs). 




And please subscribe to my YouTube and Twitch channels!

Compiling and debugging WPF

With WPF going open source it’s pretty awesome that we can no clone the code, tweak it, build it and debug right into a local copy of WPF. I see huge potential here, not just for getting bug fixes in, but for instrumenting WPF when you got those extra tricky bugs you’re trying to track down.

However, it was not simple at all to get this stuff working like that. Building it was easy, but I found it surprisingly hard to use the local build. Going back and forth with the WPF team (especially big shout-out to Steven Kirbach), I finally got it working, and already submitted a PR to update the developer documentation.

However I wanted to walk you through a quick step-by-step guide to doing this yourself. All commandline steps below are assumed to be done from the same folder (otherwise you’d have to adjust the paths)

First of all, this approach will not work with .NET Core 3.0.0-Preview6. You need the nightly Preview7, as bug in Preview 6 prevented this from working. Once Preview 7 ships, the extra Preview7-specific steps aren’t needed.

So first step go and download and install the nightly from https://github.com/dotnet/core-sdk (Get the Windows x64 Master installer).

Next open a command prompt and clone the WPF Repo (I assume you have Git installed already). Run the following command:

git clone https://github.com/dotnet/wpf

Now let’s make a small change to WPF we can later see once we get it running. For example, open wpf\src\Microsoft.DotNet.Wpf\src\WindowsBase\System\Windows\DependencyObject.cs and add the following to the DependencyObject constructor:

Debug.WriteLine("Dependency Object created : " + this.GetType().FullName);

This will cause the output window to show each dependency object getting created.

Next let’s build WPF:

wpf\build.cmd –pack

It’ll take a few minutes (especially the first time), and hopefully you won’t see any errors at the end.

OK next up let’s create a new WPF project we can use as a test, using the following command:

dotnet new wpf –o TestApp

This will create a subfolder named “TestApp”. Go into this folder and open up the TestApp.csproj file in Visual Studio. Right-click the project and select “Edit Project File” and add the following to the project below the existing property group:

  <PropertyGroup>
     <!-- Change this value based on where your local repo is located -->
     <WpfRepoRoot>..\wpf</WpfRepoRoot>
     <!-- Change based on which assemblies you build (Release/Debug) -->
     <WpfConfig>Debug</WpfConfig>
     <!-- Publishing a self-contained app ensures our binaries are used. -->
     <SelfContained>true</SelfContained>
    <!-- The runtime identifier needs to match the architecture you built WPF assemblies for. -->
    <RuntimeIdentifier>win-x86</RuntimeIdentifier>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="$(WpfRepoRoot)\artifacts\packaging\$(WpfConfig)\Microsoft.DotNet.Wpf.GitHub\lib\netcoreapp3.0\*.dll" />
    <ReferenceCopyLocalPaths Include="$(WpfRepoRoot)\artifacts\packaging\$(WpfConfig)\Microsoft.DotNet.Wpf.GitHub\lib\$(RuntimeIdentifier)\*.dll" />
  </ItemGroup>

The following steps are only necessary when using a nightly-build:

  • Save all and pick a place to save the .sln solution file (this step is important). Close Visual Studio and create a new text file “nuget.config”
  • Add the following to the nuget.config file:

<configuration>
  <packageSources>
    <add key="dotnet-core" value="https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json" />
    <add key="dotnet-windowsdesktop" value="https://dotnetfeed.blob.core.windows.net/dotnet-windowsdesktop/index.json" />
    <add key="aspnet-aspnetcore" value="https://dotnetfeed.blob.core.windows.net/aspnet-aspnetcore/index.json" />
    <add key="aspnet-aspnetcore-tooling" value="https://dotnetfeed.blob.core.windows.net/aspnet-aspnetcore-tooling/index.json" />
    <add key="aspnet-entityframeworkcore" value="https://dotnetfeed.blob.core.windows.net/aspnet-entityframeworkcore/index.json" />
    <add key="aspnet-extensions" value="https://dotnetfeed.blob.core.windows.net/aspnet-extensions/index.json" />
    <add key="gRPC repository" value="https://grpc.jfrog.io/grpc/api/nuget/v3/grpc-nuget-dev" />
  </packageSources>
</configuration>

Open the solution back up and build and run. With a little luck your app should launch and you’ll see something like this in the Output Window confirming our change made it (or course you can now also step right into source locally on disk):

Annotation 2019-06-20 213538

Hacking the Silverlight Unit Tests to support returning Task

The Silverlight/Windows Phone unit test framework has always supported running asynchronous tests – a feature that until recently wasn’t there in WPF without jumping some really ugly (and flaky) hoops. Basically you can write a silverlight and windows phone unit test like this:

[TestClass]
public class TestClass1 : SilverlightTest
{
    [TestMethod]
    [Asynchronous] 
public void Test1() { DispatcherTimer timer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(2) }; timer.Tick += (a, b) => { timer.Stop(); base.TestComplete(); }; timer.Start(); } }

The problem with this code though is that this is only for Silverlight and Windows Phone. If you are cross-compiling for multiple platforms and want to run on WPF this wouldn’t work. It’s also not pretty that you have to inherit from SilverlightTest, remember to decorate the class with [Asynchronous] as well as calling TestComplete. Even worse, if you forget to stop the timer, it would CRASH the entire test run. The unit test framework is a little flaky when it comes to a task accidentally completing twice (instead of reporting it as an error, it crashes the entire test run and you’ll never get your daily test report…).

With Visual Studio 2012 and .NET 4.5 we can now simply return an object of type ‘Task’ and we would be good to go. This is awesome for testing your new async/await based stuff that returns task. So in WPF you would simply return your task object. As an example, let’s say we have the following really advanced computing task:

public static Task<int> Compute(int input)
{
    TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();
    DispatcherTimer timer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(2) };
    timer.Tick += (a, b) =>
    {
        timer.Stop();
        if (input <= 0)
            tcs.SetException(new ArgumentOutOfRangeException("Number must be greater than 0"));
        else 
            tcs.SetResult(input);
    };
    timer.Start();
    return tcs.Task;
}

Now to test this in .NET 4.5 (including Windows Store Apps) you can simply write the following unit test:

[TestClass] 
public class TestClass1
{
[TestMethod] public async Task Test42() { var result = await Utility.Compute(42); Assert.AreEqual(result, 42); }
}

Nice and simple. However in Silverlight and Windows Phone you would have to write the following instead (I highlighted the extra or changed code required):

[TestClass]
public class TestClass1 : SilverlightTest
{
    [TestMethod]
    [Asynchronous]
    public async void Test42()
    {
        var result = await Utility.Compute(42);
        Assert.AreEqual(result, 42);
        base.TestComplete();
    }
}

Wouldn’t it be nice if the unit test I just wrote for WPF would work as is in Silverlight and on Windows Phone? Of course you could create a SilverlightTest class that has an empty TestComplete method, define an AsynchronousAttribute just for fun, and sprinkle a compiler conditional around the void/Task return type, but that just feels messy to me.

Fortunately the unit test framework for Silverlight is open source, so it’s possible to hack it in there. There are two main places you will need to change, which I will go through here. Note this is based on changeset #80285.

In the file “\Microsoft.Silverlight.Testing\UnitTesting\UnitTestMethodContainer.cs” we add the highlighted code to the method that detects if the Asynchronous attribute is on a method:

private bool SupportsWorkItemQueue()
{
    if (_testMethod != null)
    {
        if (_testMethod.Method.ReturnType != null && 
            _testMethod.Method.ReturnType == typeof(System.Threading.Tasks.Task) ||
            _testMethod.Method.ReturnType.IsSubclassOf(typeof(System.Threading.Tasks.Task)))
            return true; //Task Support
        else
            return ReflectionUtility.HasAttribute(_testMethod, typeof(AsynchronousAttribute));
    }
    else if (MethodInfo != null)
    {
        return ReflectionUtility.HasAttribute(MethodInfo, typeof(AsynchronousAttribute));
    }
    else
    {
        return false;
    }
}

Next is modifying the Invoke method that executes your test, which is located in ‘Microsoft.Silverlight.Testing\Metadata\VisualStudio\TestMethod.cs’. This is where the main work is done to enable tasks to work:

public virtual void Invoke(object instance)
{
    _methodInfo.Invoke(instance, None);
}

This now changes to:

public virtual void Invoke(object instance, CompositeWorkItem workItem)
{
    var t = _methodInfo.Invoke(instance, None) as System.Threading.Tasks.Task;
    if (t != null)
    {
        if (t.IsFaulted)
        {
            throw t.Exception;
        }
        else if (!t.IsCompleted)
        {
            var context = System.Threading.SynchronizationContext.Current;
            t.ContinueWith(result =>
            {
                context.Post((d) =>
                {
                    if (result.IsFaulted)
                    {
                        Exception ex = result.Exception;
                        if (ex is AggregateException)
                            ex = ex.GetBaseException();
                        workItem.WorkItemException(ex);
                    }
                    else
                        workItem.WorkItemCompleteInternal();
                }, null);
            });
        }
    }
}

Basically it grabs the task that is returned and calls the code that TestComplete would have called or what a raised exception would have called in case the test raises an exception. Also note that we changed the signature of the method to give us the CompositeWorkItem we need to raise these events on. This change does affect quite a lot of other code, but it’s merely a matter of adding the same parameter there as well, and the only place that calls this method (which is the CompositeWorkItem) to set this parameter to ‘this’.

Now you can also write tests that tests for exceptions thrown. Often you don’t even need to await the result in those cases:

[TestMethod]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public Task TestOutOfRange()
{
    return Utility.Compute(0);  //no need to await
}

[TestMethod]
public Task TestOutOfRange_Failure() //This test will fail
{
    return Utility.Compute(0);
}

And here’s what that looks like for the entire test run:

image

To make it easy on you, you can download the modified unit test framework source here.

…But EVEN better: Go vote for this to be part of the official toolkit here:  http://silverlight.codeplex.com/workitem/11457

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’.

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

Overwriting the default WebRequest used by WebClient

In Silverlight/WPF and WPF there’s today a WebClient class for making webrequests. Under the covers it creates HttpWebRequest for sending the request and HttpWebResponse for handling the response coming back from the server. In an older blogpost, I created a custom WebClient for WP7 that added support for GZIP compression this way.

However the default WebClient doesn’t actually create an “HttpWebRequest/Response” object, since this is an abstract class. What it really does is create internal subclasses that is then used. This is handled by the WebRequestCreator static class which really creates these classes for you. However a less-known feature is that you can actually tell your application that you want to use a specific client for handling the web request and responses for specific domains. You might actually already have fiddled with this in Silverlight if you wanted to explicitly let Silverlight handle the web requests instead of handing it off to the hosting browser control using the following statement:

WebRequest.RegisterPrefix("http://www.mydomain.com/", WebRequestCreator.ClientHttp);

This call makes all requests to www.mydomain.com go through the ClientHttp. As mentioned it’s possible to make your own requestor and completely intercept ANY requests made by WebClient!

If you have your own HttpWebRequest implementation ‘MyHttpWebRequest’, this would look something like this:

public static class MyWebRequestCreator
{
    private static IWebRequestCreate myCreator;

    public static IWebRequestCreate MyHttp
    {
        get
        {
            if (myCreator == null)
            {
                myCreator = new MyHttpRequestCreator();
            }
            return myCreator;
        }
    }

    private class MyHttpRequestCreator : IWebRequestCreate
    {
        public WebRequest Create(Uri uri)
        {
            return new MyHttpWebRequest(uri);
        }
    }
}

So now you can just call:

WebRequest.RegisterPrefix("http://", MyWebRequestCreator.MyHttp);
WebRequest.RegisterPrefix("https://", MyWebRequestCreator.MyHttp);

…and ALL web requests to http or https websites, will be routed through your MyHttpWebRequest class (which you granted still have to build). This class could just wrap the built-in ClientHttpWebRequest and you can modify/add/remove/decode stuff to your pleasing. This is awesome for test framework mock ups, but it’s also really neat for the GZIP WebClient control I mentioned earlier. Why? Well to use my GZipWebClient, you would have to go through all your code and change:

WebClient client = new WebClient();

to

WebClient client = new SharpGIS.WebClient();

This can be a lot of work, and even if you did that, what about all the 3rd party libraries you use, where you can’t go in and change that? Well enter RegisterPrefix! Do you want GZIP support in Hammock? Done! Do you want GZIP support in RestSharp? Done!* Do you want GZIP support in [insert favorite API here]? Done!

*Update: Actually this might not be the case. Some libraries uses some features that either is not possible to implement with the custom HttpWebRequest (like UserAgent), and I didn’t add support for Cookies as well. Both of these are for instance used by RestSharp.

So I went ahead and updated my Nuget Package for the GZipWebClient, so go grab v1.1, and you will only have to add 1-2 LINES OF CODE, and just execute it ONCE (for instance at startup), and EVERYTHING WebClient will be enhanced with GZIP compression. You can also grab the updated source on the original blogpost here.

I really have to give some credit to my co-worker Anargyros for this one, who mentioned that it might be possible to do it this way. Go follow him on twitter and give him some twitter love @tomahawk1187

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.

WinRT vs. Silverlight - Part 7 - Making WebRequests

See intro blogpost here.

In Silverlight and WPF you are probably used to using WebClient to perform downloads. This is a simple class for doing download/upload string or retrieving a response stream from the server. However, in Windows Runtime this client doesn’t exists. Instead we have new a simple “HttpClient” to do much of what WebClient can. However it works very differently by using the new Task framework, and the more you dive into porting code to WinRT, you will see this a lot, and it will make your life porting code cumbersome. On the upside, the Tasks framework is awesome and it’ll often simplify you code a great deal! I talked a bit about this in my previous post, so please read that first, before you continue here, since this will be building on top of that.

Let’s say we have a method in WPF and Silverlight that uses WebClient to downloada and create an image. Since this is working asynchronously, we would have to either use event handlers or action delegates to return the result and/or the error. The method could look something like this:

public void GetContent(Uri uri, Action<string> complete, Action<Exception> error)
{
    WebClient client = new WebClient();
    client.DownloadStringCompleted += (sender, e) =>
    {
        if (e.Error != null)
            error(e.Error);
        else {
            complete(e.Result);
        }
    };
    client.DownloadStringAsync(uri);
}

 

Here’s how a method like that could look in WinRT:

public async Task<string> GetContentI(Uri uri)
{
   System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
   var result = await client.GetAsync(uri);
   return result.Content.ReadAsString();
}

Simple right? Well it' gets even simpler when we have to start consuming that method.

From SL and WPF you would consume the method something like this:

GetContent(uri, (text) => {
          TextBlock tb = new TextBlock() { Source = text };
          LayoutRoot.Children.Add(tb);
      },
      (error) => { /*TODO: handle error*/ }
);

And the same using the Task framework:

try {
   TextBlock tb = new TextBlock() { Source = await GetContent(uri) };
   LayoutRoot.Children.Add(tb);
catch { /*TODO: handle error */ }

You tell me what’s more elegant and readable? Smile

My point here is that Tasks are awesome, so rather than trying to reuse your existing code in WinRT, consider rewriting your existing code to use Tasks and it will work much smoother.

There’s lets create a method for downloading a string over the network that works the same way across the board. (I’ll assume you are using the Async Task CTP for Silverlight or WPF for this).

public async Task<string> GetContent(Uri uri)
{
#if NETFX_CORE
    System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
    var reqResult = await client.GetAsync(uri);
    return reqResult.Content.ReadAsString();
#else
    WebClient client = new WebClient();
    TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
    client.DownloadStringCompleted += (sender, e) =>
    {
        if (e.Error != null)
            tcs.TrySetException(e.Error);
        else
            tcs.TrySetResult(e.Result);
    };
    client.DownloadStringAsync(uri);
    return await tcs.Task;
#endif
}

Note you could also use the new .NET method “WebClient.DownloadStringTaskAsync” which would simplify the above quite a lot. I used the event based approach to demonstrate how you would handle the cases where you don’t already have a task implementation available.

WinRT vs. Silverlight - Part 6 - Using Tasks

See intro blogpost here.

When you start working with WinRT, you start seeing classes missing or changed. A lot of methods are now only asynchronous, like making a web request, opening, reading and writing files etc. They all now on the Task framework, and they do this to ensure you application is always responsive. However without this framework, it would be a pain to code against an API that’s inherently asynchronous all the way through. But with it, it makes it really easy to write code against it.

As an example here’s how you normally write async operations in WPF and Silverlight:

var myObject = new MyClass();
myObject.Completed += (sender,e) => { 
   //Completed event handler 
if(e.Error == null) { statusText.Text = "My Operation has completed: " + e.Result;
} }; myObject.StartAsync(); //Starts process and fires "Completed" event when done

So we first hook up to the event handler, then call start. When you look at the code, the lines are not executed in the order they are written. The completed delegate executes after the operation completes after Start() has been run (even explaining it makes it sound confusing). Also you cannot throw exceptions from an asynchronous running process, because there will be no way to catch it, so you’ll have to parse an exception object back as part of your result and check it.

This pattern makes it hard to read and understand the code, since it’s not immediately obvious what code runs when. Especially when the code gets more complex and/or your eventhandlers are declared elsewhere. When we then nest events, it gets very convoluted quickly:

var myObject = new MyClass();
myObject.Completed += (sender,e) => { 
   if(e.Error == null) {
       //Perform next operation
       var myObject2 = new MyClass();
       myObject2.Completed += (sender2,e2) => { 
           if(e2.Error == null) {
              //Completed event handler
              statusText.Text = "My Operation has completed: " + e2.Result;
} }; myObject2.StartAsync(); } }; myObject.StartAsync();

With the Task framework this becomes very simple and straightforward to write and more importantly read:

var myObject = new MyClass();
try {
     string result = await myObject.StartAsync();
     var myObject2 = new MyClass();
     string result2 = await myObject2.StartAsync();
     statusText.Text = "My Operation has completed: " + result2;
} catch { }

Notice that we don’t bother with checking an error object. We simply use try/catch instead, and the task returns the result up front. If it wasn’t for the little “await” keyword, it looks like this is just good ol’ synchronous programming! This is pure awesomeness!

If you are planning on porting a large application from Silverlight or WPF and it uses a lot of event-based asynchronous programming, you are probably in for some work. Not to say that your application can’t use events, but a lot of the WinRT API’s don’t have eventhandlers any more, so if you insist on keeping it this way, you would have to wrap all the built in tasks into some event-based classes. I would probably rather focus on moving forward and getting this cleaned up. And since the Task framework is already available in .NET 4 and there’s a CTP for Silverlight (and included in upcoming v5!) and WinPhone, you could port your original code to start taking advantage of this, making your code reuse easier and cleaner moving forward.

So how would you go about wrapping an event-based class into a task based method? Well let’s continue using the MyClass example above, and wrap it in a task. Here’s how that would look:

public Task<string> StartAsync()
{
    var tcs = new TaskCompletionSource<string>();
    var obj = new MyClass();
    obj.Completed += (sender,e) => {
        if (e.Error != null)
              tcs.TrySetException(e.Error);
        else
              tcs.TrySetResult(e.Result);
    };
    obj.StartAsync();
    return tcs.Task;
}

Basically we return Task of string, instead of just a string. We use the TaskCompletionSource of string to handle error and result messaging back to the task.

So when should you make a method an asynchronous task? The rule of thumb is: If it takes more than 50ms to execute, it should be asynchronous! This helps a lot towards preventing the UI from becoming choppy and/or unresponsive.