Loading indicator for content controls

With C# 5 (.NET 4.5) it became a lot easier to create asynchronous methods. There’s also a great MSDN article on how to leverage this using MVVM so that you can have properties update the view when they’ve finished loading. What I wanted was a simple control that would indicate to the user that the content was being fetched (via binding to the NotifyTaskCompletion.IsNotCompleted property).

What I wanted though was a simple attached property on a ContentControl (or HubSection in my case but it’s easy to modify for other control types) and it would switch to the loading indicator based on the bound value, as I didn’t want to have to modify lots of DataTemplates to add the indicator to them and then mess around with the visibility of the content/indicator based on if the value was being loaded or not.

The actual visual part of the control is straight forward:

public sealed class AsyncIndicator : Control
{
    protected override Size MeasureOverride(Size availableSize)
    {
        Size desiredSize = base.MeasureOverride(availableSize);

        return new Size(
            GetSize(availableSize.Width, desiredSize.Width),
            GetSize(availableSize.Height, desiredSize.Height));
    }

    private static double GetSize(double available, double desired)
    {
        return double.IsPositiveInfinity(available) ? desired : available;
    }
}

All this does is make the control take all the available size of the parent, taking into account if the parent provides us with an infinite amount of space (e.g. StackPanel). Here’s the simple template for it, which I tuck away inside Generic.xaml:

<Style TargetType="controls:AsyncIndicator">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="controls:AsyncIndicator">
                <Border Background="#33888888">
                    <StackPanel HorizontalAlignment="Center"
                                VerticalAlignment="Center">
                        <ProgressRing HorizontalAlignment="Center"
                                      IsActive="True" />

                        <TextBlock Style="{ThemeResource BodyTextBlockStyle}"
                                   Text="Loading" />
                    </StackPanel>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Like I said, nothing complex about this nor nothing that would really warrant a new control; it’s just a spinning progress (new to WinRT) with a label. However, I’m also going to store the attached property in this control. How the attached property works is when it’s set to true it will replace the ContentTemplate property of the attached control to one which just contains the loading indicator; when it’s set to false it restores the original value to the attached control. Therefore, I’m going to use two dependency properties, a public one for the attached property and a private one for storing the current value of the ContentTemplate before it is overwritten.

public static readonly DependencyProperty IsLoadingProperty =
    DependencyProperty.RegisterAttached("IsLoading", typeof(bool), typeof(AsyncIndicator), new PropertyMetadata(false, OnIsLoadingChanged));

private static readonly DependencyProperty OriginalTemplateProperty =
    DependencyProperty.RegisterAttached("OriginalTemplate", typeof(TemplateData), typeof(AsyncIndicator), new PropertyMetadata(null));

public static bool GetIsLoading(DependencyObject obj)
{
    return (bool)obj.GetValue(IsLoadingProperty);
}

public static void SetIsLoading(DependencyObject obj, bool value)
{
    obj.SetValue(IsLoadingProperty, value);
}

private static void OnIsLoadingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    if ((bool)e.NewValue)
    {
        TemplateData data = BackupTemplateProperty(d);
        if (data != null)
        {
            SetIndicator(d, data);
        }
    }
    else
    {
        RestoreTemplateProperty(d);
    }
}

private class TemplateData
{
    public DependencyProperty Property { get; set; }

    public object Template { get; set; }
}

The reason for the private TemplateData nested class is to allow for different properties of different controls to be backed up, replaced and restored (at the moment I need ContentControl and HubSection, which don’t share the same ContentTemplate property). Here’s the actual code which switches out the current template and replaces it with one that just contains the new control:

private static DependencyProperty GetTemplateProperty(object element)
{
    if (element is ContentControl)
    {
        return ContentControl.ContentTemplateProperty;
    }
    else if (element is HubSection)
    {
        return HubSection.ContentTemplateProperty;
    }

    return null;
}

private static TemplateData BackupTemplateProperty(DependencyObject d)
{
    TemplateData data = null;

    DependencyProperty templateProperty = GetTemplateProperty(d);
    if (templateProperty != null)
    {
        data = new TemplateData();
        data.Property = templateProperty;
        data.Template = d.GetValue(templateProperty);
    }

    d.SetValue(OriginalTemplateProperty, data);
    return data;
}

private static void RestoreTemplateProperty(DependencyObject d)
{
    var data = (TemplateData)d.GetValue(OriginalTemplateProperty);
    if (data != null)
    {
        d.SetValue(data.Property, data.Template);
        d.ClearValue(OriginalTemplateProperty);
    }
}

private static void SetIndicator(DependencyObject d, TemplateData data)
{
    // Note: The namespace must match the namespace this class belongs to.
    const string IndicatorDataTemplate =
@"<DataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
                xmlns:local='using:PurplePhobos.View.Controls'>
    <local:AsyncIndicator />
</DataTemplate>";

    d.SetValue(data.Property, XamlReader.Load(IndicatorDataTemplate));
}

To keep the code generalised, it tries to find a suitable dependency property based on the type of the control it is being attached to. If it finds a property it then saves the current value of it to our private attached property (this also works fine for static resources, however, it won’t work for bindings, but there shouldn’t be much need for a binding of a DataTemplate). A new DataTemplate is created from a string that contains the new control – note if you use this code and change the namespace of where the class is be sure to update the string as well to the new namespace! Finally restoring is a lot easier, the control just needs to check if a template property has been backed up to the private attached property and, if so, set it back (clearing the OriginalTemplateProperty to reduce resources).

The full class can be found here – you’ll just need to style it somewhere in your app. Usage is something like this:

<HubSection ctrls:AsyncIndicator.IsLoading="{Binding Property.IsNotCompleted}"
            ContentTemplate="{StaticResource ExampleTemplate}" />

WeakEventManager for WinRT

When registering to an event with an instance method then a reference will be stored from the event source to the event handler. This is normally fine, however, there are situations when the event source may live longer than the event handler. An example I recently ran into was when I wanted to listen to the Clipboard.ContextChanged event, which is static.

In WPF land you’d use the WeakEventManager<TEventSource, TEventArgs> class, however, this isn’t available to Window Store apps, so let’s build it! I’ve changed the API slightly, as I needed overloads to accept a Type due to Clipboard being a static class (which you can’t use for generic type parameters). So, here’s what I ended up with to register the event:

WeakEventManager.AddHandler<object>(
    typeof(Clipboard),
    "ContentChanged",
    this.OnClipboardContentChanged);

Here’s the main class – the actual logic is performed by the nested class:

using System;
using System.Collections.Generic;
using System.Reflection;

/// <summary>
/// Implements a weak event listener that allows the owner to be garbage
/// collected if its only remaining link is an event handler.
/// </summary>
public static class WeakEventManager
{
    private readonly static List<WeakEvent> registeredEvents = new List<WeakEvent>();

    /// <summary>
    /// Adds the specified event handler to the specified event.
    /// </summary>
    /// <typeparam name="TEventArgs">The type that holds the event data.</typeparam>
    /// <param name="sourceType">
    /// The type of the class that contains the specified event.
    /// </param>
    /// <param name="eventName">The name of the event to subscribe to.</param>
    /// <param name="handler">The delegate that handles the event.</param>
    public static void AddHandler<TEventArgs>
        (Type sourceType, string eventName, EventHandler<TEventArgs> handler)
    {
        EventInfo eventInfo = sourceType.GetRuntimeEvent(eventName);
        registeredEvents.Add(
            new WeakEvent(null, eventInfo, handler));
    }

    /// <summary>
    /// Adds the specified event handler to the specified event.
    /// </summary>
    /// <typeparam name="TEventSource">The type that raises the event.</typeparam>
    /// <typeparam name="TEventArgs">The type that holds the event data.</typeparam>
    /// <param name="source">
    /// The source object that raises the specified event.
    /// </param>
    /// <param name="eventName">The name of the event to subscribe to.</param>
    /// <param name="handler">The delegate that handles the event.</param>
    public static void AddHandler<TEventSource, TEventArgs>
        (TEventSource source, string eventName, EventHandler<TEventArgs> handler)
    {
        EventInfo eventInfo = typeof(TEventSource).GetRuntimeEvent(eventName);
        registeredEvents.Add(
            new WeakEvent(source, eventInfo, handler));
    }

    /// <summary>
    /// Removes the specified event handler from the specified event.
    /// </summary>
    /// <typeparam name="TEventArgs">The type that holds the event data.</typeparam>
    /// <param name="sourceType">
    /// The type of the class that contains the specified event.
    /// </param>
    /// <param name="eventName">
    /// The name of the event to remove the handler from.
    /// </param>
    /// <param name="handler">The delegate to remove.</param>
    public static void RemoveHandler<TEventArgs>
        (Type sourceType, string eventName, EventHandler<TEventArgs> handler)
    {
        EventInfo eventInfo = sourceType.GetRuntimeEvent(eventName);
        foreach (WeakEvent weakEvent in registeredEvents)
        {
            if (weakEvent.IsEqualTo(null, eventInfo, handler))
            {
                weakEvent.Detach();
                break;
            }
        }
    }

    /// <summary>
    /// Removes the specified event handler from the specified event.
    /// </summary>
    /// <typeparam name="TEventSource">The type that raises the event.</typeparam>
    /// <typeparam name="TEventArgs">The type that holds the event data.</typeparam>
    /// <param name="source">
    /// The source object that raises the specified event, or null if it's
    /// a static event.
    /// </param>
    /// <param name="eventName">
    /// The name of the event to remove the handler from.
    /// </param>
    /// <param name="handler">The delegate to remove.</param>
    public static void RemoveHandler<TEventSource, TEventArgs>
        (TEventSource source, string eventName, EventHandler<TEventArgs> handler)
    {
        EventInfo eventInfo = typeof(TEventSource).GetRuntimeEvent(eventName);
        foreach (WeakEvent weakEvent in registeredEvents)
        {
            if (weakEvent.IsEqualTo(source, eventInfo, handler))
            {
                weakEvent.Detach();
                break;
            }
        }
    }

    private class WeakEvent
    {
        // Implementation details to follow
    }
}

Naturally, in production you’d want some argument validation (i.e. not nulls and that GetRuntimeEvent returned something), but to keep the code simple I’ve omitted it. The actual logic goes in the WeakEvent nested class. This is needed because you can’t just keep a weak reference to the event handler object, as this most likely will be a temporary object that will soon get garbage collected. You also can’t keep a strong reference to the event handler, as it has a reference to the instance of the target so will keep it alive, defeating the point of the class! Therefore, the WeakEvent class has to wrap the parts of the event handler delegate in a way that allows the target class to be garbage collected. Here’s how I’ve approached it:

private class WeakEvent
{
    private static readonly MethodInfo onEventInfo =
        typeof(WeakEvent).GetTypeInfo().GetDeclaredMethod("OnEvent");

    private EventInfo eventInfo;
    private object eventRegistration;
    private MethodInfo handlerMethod;
    private WeakReference<object> handlerTarget;
    private object source;

    public WeakEvent(object source, EventInfo eventInfo, Delegate handler)
    {
        this.source = source;
        this.eventInfo = eventInfo;

        // We can't store a reference to the handler (as that will keep
        // the target alive) but we also can't store a WeakReference to
        // handler, as that could be GC'd before its target.
        this.handlerMethod = handler.GetMethodInfo();
        this.handlerTarget = new WeakReference<object>(handler.Target);

        object onEventHandler = this.CreateHandler();
        this.eventRegistration = eventInfo.AddMethod.Invoke(
            source,
            new object[] { onEventHandler });

        // If the AddMethod returned null then it was void - to
        // unregister we simply need to pass in the same delegate.
        if (this.eventRegistration == null)
        {
            this.eventRegistration = onEventHandler;
        }
    }

    public void Detach()
    {
        if (this.eventInfo != null)
        {
            WeakEventManager.registeredEvents.Remove(this);

            this.eventInfo.RemoveMethod.Invoke(
                this.source,
                new object[] { eventRegistration });

            this.eventInfo = null;
            this.eventRegistration = null;
        }
    }

    public bool IsEqualTo(object source, EventInfo eventInfo, Delegate handler)
    {
        if ((source == this.source) && (eventInfo == this.eventInfo))
        {
            object target;
            if (this.handlerTarget.TryGetTarget(out target))
            {
                return (handler.Target == target) &&
                        (handler.GetMethodInfo() == this.handlerMethod);
            }
        }

        return false;
    }

    public void OnEvent<T>(object sender, T args)
    {
        object instance;
        if (this.handlerTarget.TryGetTarget(out instance))
        {
            this.handlerMethod.Invoke(instance, new object[] { sender, args });
        }
        else
        {
            this.Detach();
        }
    }

    private object CreateHandler()
    {
        Type eventType = this.eventInfo.EventHandlerType;
        ParameterInfo[] parameters = eventType.GetTypeInfo()
                                                .GetDeclaredMethod("Invoke")
                                                .GetParameters();

        return onEventInfo.MakeGenericMethod(parameters[1].ParameterType)
                            .CreateDelegate(eventType, this);
    }
}

Basically the parts of the delegate have been stored in two parts; the method to invoke (stored as a normal reference) and the target to invoke the method on (stored as a weak reference). The tricky part is registering our handler on the event via reflection, made more difficult because events in the core WinRT classes are slightly different to the .NET events (for example, the add method of the event returns an EventRegistrationToken that must be passed in to the remove method; .NET events return void for the add method and require the delegate passed into the add method for the parameter to the remove method). When we get called back we have a quick check to see if our target is still valid; if it isn’t then we unregister from the event (after all, we’ve got nothing to do when it’s invoked in the future!), which allows the GC to clean up the WeakEvent instance (not that it should be that heavy anyway).

Defining MessageDialogs in XAML

I’m a fan of the MVVM pattern and recently needed to present a dialog (actually a MessageDialog in WinRT) to the user if they were about to leave the data entry window but hadn’t saved their changes. I initially thought that the view model would need to create a dialog, however, I thought about it some more and came to the conclusion that actually the view should be responsible for this – the view model only needs to let the view know that it has unsaved changes and provide commands to the view (which will expose them to the user) for it to either save and close or close without saving.

So the next thing I needed was to be able to define a dialog in XAML, as I wanted to bind the buttons on the dialog to the commands in the view model. As well as defining it in the XAML, I wanted to either launch it in response to the user clicking a button or, if the dialog isn’t required (i.e. there are no unsaved changes in my scenario) make the button perform the default action without prompting the user. To do this I’ve used an attached property which, when set on a button, will subscribe to the Click event and show the dialog in the handler, if required, or perform the default action if the PromptUser property is set to false. The resulting XAML looks something like this (note that the MessageDialogTemplate can be moved to a resource, I’ve put it inline here to make the code snippet shorter and easier to follow):

<AppBarButton Icon="Cancel"
              Label="Close">
    <dlg:MessageDialogTemplate.ShowOnClick>
        <dlg:MessageDialogTemplate Content="You have unsaved changes to the document."
                                   ShowDialog="{Binding HasUnsavedChanges}">
            <dlg:DialogCommand Command="{Binding SaveAndClose}"
                               Label="Save changes" />
							   
            <dlg:DialogCommand Command="{Binding Cancel}"
                               Label="Discard changes" />

            <!-- If no command is specified then the button will -->
            <!-- do dismiss the dialog without triggering any action. -->
            <dlg:DialogCommand Label="Cancel" />
        </dlg:MessageDialogTemplate>
    </dlg:MessageDialogTemplate.ShowOnClick>
</AppBarButton>

So, that’s it’s usage. For the above there are two classes required:

namespace DialogHelper
{
    using System.Windows.Input;
    using Windows.UI.Popups;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Markup;

    [ContentProperty(Name = "Label")]
    public sealed class DialogCommand : FrameworkElement
    {
        public static readonly DependencyProperty CommandParameterProperty =
            DependencyProperty.Register("CommandParameter", typeof(object), typeof(DialogCommand), new PropertyMetadata(null));

        public static readonly DependencyProperty CommandProperty =
            DependencyProperty.Register("Command", typeof(ICommand), typeof(DialogCommand), new PropertyMetadata(null));

        public static readonly DependencyProperty LabelProperty =
            DependencyProperty.Register("Label", typeof(string), typeof(DialogCommand), new PropertyMetadata(string.Empty));

        public ICommand Command
        {
            get { return (ICommand)this.GetValue(CommandProperty); }
            set { this.SetValue(CommandProperty, value); }
        }

        public object CommandParameter
        {
            get { return this.GetValue(CommandParameterProperty); }
            set { this.SetValue(CommandParameterProperty, value); }
        }

        public string Label
        {
            get { return (string)GetValue(LabelProperty); }
            set { SetValue(LabelProperty, value); }
        }

        internal void Invoke(IUICommand command)
        {
            if (this.Command != null)
            {
                this.Command.Execute(this.CommandParameter);
            }
        }
    }
}

Nothing too special about this class, apart from it inherits from FrameworkElement so that it gets the inheriting data context scaffolding, which means you can use bindings for the commands and they will pick it up from the button the dialog is attached to. Also worth noting is that originally I tried to make the class implement the IUICommand interface, however, because the dialog is running on a different thread to what the dependency properties were created on, there were some exceptions when the MessageDialog would try to read the values from the properties. Instead, as shown in the next class, these commands are translated into UICommands.

namespace DialogHelper
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Collections.Specialized;
    using Windows.UI.Popups;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Controls.Primitives;
    using Windows.UI.Xaml.Markup;

    [ContentProperty(Name = "Commands")]
    public sealed class MessageDialogTemplate : Panel
    {
        public static readonly DependencyProperty CancelCommandIndexProperty =
            DependencyProperty.Register("CancelCommandIndex", typeof(int), typeof(MessageDialogTemplate), new PropertyMetadata(-1));

        public static readonly DependencyProperty ContentProperty =
            DependencyProperty.Register("Content", typeof(string), typeof(MessageDialogTemplate), new PropertyMetadata(string.Empty));

        public static readonly DependencyProperty DefaultCommandIndexProperty =
            DependencyProperty.Register("DefaultCommandIndex", typeof(int), typeof(MessageDialogTemplate), new PropertyMetadata(-1));

        public static readonly DependencyProperty PromptUserProperty =
            DependencyProperty.Register("PromptUser", typeof(bool), typeof(MessageDialogTemplate), new PropertyMetadata(true));

        public static readonly DependencyProperty ShowOnClickProperty =
            DependencyProperty.RegisterAttached("ShowOnClick", typeof(MessageDialogTemplate), typeof(MessageDialogTemplate), new PropertyMetadata(null, OnShowOnClickChanged));

        public static readonly DependencyProperty TitleProperty =
            DependencyProperty.Register("Title", typeof(string), typeof(MessageDialogTemplate), new PropertyMetadata(string.Empty));

        private readonly ObservableCollection<DialogCommand> commands =
            new ObservableCollection<DialogCommand>();

        public MessageDialogTemplate()
        {
            this.commands.CollectionChanged += OnCommandsCollectionChanged;
        }

        public int CancelCommandIndex
        {
            get { return (int)this.GetValue(CancelCommandIndexProperty); }
            set { this.SetValue(CancelCommandIndexProperty, value); }
        }

        public IList<DialogCommand> Commands
        {
            get { return this.commands; }
        }

        public string Content
        {
            get { return (string)this.GetValue(ContentProperty); }
            set { this.SetValue(ContentProperty, value); }
        }

        public int DefaultCommandIndex
        {
            get { return (int)this.GetValue(DefaultCommandIndexProperty); }
            set { this.SetValue(DefaultCommandIndexProperty, value); }
        }

        public bool PromptUser
        {
            get { return (bool)this.GetValue(PromptUserProperty); }
            set { this.SetValue(PromptUserProperty, value); }
        }

        public string Title
        {
            get { return (string)this.GetValue(TitleProperty); }
            set { this.SetValue(TitleProperty, value); }
        }

        public static MessageDialogTemplate GetShowOnClick(DependencyObject obj)
        {
            return (MessageDialogTemplate)obj.GetValue(ShowOnClickProperty);
        }

        public static void SetShowOnClick(DependencyObject obj, MessageDialogTemplate value)
        {
            obj.SetValue(ShowOnClickProperty, value);
        }

        private static void OnButtonClick(object sender, RoutedEventArgs e)
        {
            MessageDialogTemplate template = GetShowOnClick(sender as DependencyObject);
            if (template != null)
            {
                template.OnButtonClick();
            }
        }

        private static void OnButtonDataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
        {
            MessageDialogTemplate template = GetShowOnClick(sender);
            if (template != null)
            {
                template.DataContext = sender.DataContext;
            }
        }

        private static void OnShowOnClickChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var button = d as ButtonBase;
            if (button != null)
            {
                button.Click += OnButtonClick;
                button.DataContextChanged += OnButtonDataContextChanged;
            }
        }

        private void ExecuteDefaultCommand()
        {
            int index = this.DefaultCommandIndex;
            if (index == -1)
            {
                // Guidlines state that if not specified, the default is the
                // leftmost button.
                index = 0;
            }

            if (index < this.commands.Count)
            {
                DialogCommand command = this.commands[index];
                if ((command != null) && (command.Command != null))
                {
                    command.Command.Execute(command.CommandParameter);
                }
            }
        }

        private void OnCommandsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            this.Children.Clear();
            foreach (DialogCommand command in this.commands)
            {
                this.Children.Add(command);
            }
        }

        private void OnButtonClick()
        {
            if (this.PromptUser)
            {
                this.ShowMessageDialog();
            }
            else
            {
                this.ExecuteDefaultCommand();
            }
        }

        private async void ShowMessageDialog()
        {
            var dialog = new MessageDialog(this.Content, this.Title);

            foreach (DialogCommand command in this.commands)
            {
                dialog.Commands.Add(
                    new UICommand(command.Label, command.Invoke));
            }

            dialog.CancelCommandIndex = (uint)this.CancelCommandIndex;
            dialog.DefaultCommandIndex = (uint)this.DefaultCommandIndex;

            await dialog.ShowAsync();
        }
    }
}

It may seem strange to not bind the DataContext to the DataContext of the button, however, I was bit by the bug where changes to the parent data context are not propagated through the binding (see this blog for more details) – strangely enough changes to the parent’s data context do cause the buttons DataContextChanged event to fire, which makes it even more confusing the binding doesn’t work!?

I’m quite pleased with the result; it’s nice to define the dialog layout in the XAML with the rest of the UI and the view model doesn’t need to raise some event that the view has to listen for (which seems to be the way for it to show a dialog in most examples I’ve seen.)

DataTemplates in WinRT

While I enjoy the simpler interfaces in WinRT, I’ve been spoiled by the power of WPF. One thing I missed recently was the automatic selection of a DataTemplate based on the DataType property; this property isn’t there in WinRT.

The solutions I’ve seen use a custom DataTemplateSelector with various properties for each type. This certainly works but it felt a bit repetitive. Instead, the solution I came up with searches the resources for an item with the same key as the type name and returns that. Here’s the class:

namespace AutoDataTemplate
{
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Media;

    public sealed class AutoDataTemplateSelector : DataTemplateSelector
    {
        protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
        {
            if (item == null)
            {
                return null;
            }

            object key = item.GetType().Name;
            return FindResource(key, container as FrameworkElement) as DataTemplate;
        }

        private static object FindResource(object key, FrameworkElement element)
        {
            if (element == null)
            {
                return null;
            }

            object value;
            if (element.Resources.TryGetValue(key, out value))
            {
                return value;
            }

            return FindResource(key, VisualTreeHelper.GetParent(element) as FrameworkElement);
        }
    }
}

Using this class would be something like this:

<Page x:Class="AutoDataTemplate.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:adt="using:AutoDataTemplate">

    <Page.Resources>
        <adt:AutoDataTemplateSelector x:Key="AutoSelector" />
        
        <DataTemplate x:Key="ClassType1">
            <TextBlock Foreground="CornflowerBlue"
                       Text="{Binding Value}" />
        </DataTemplate>

        <DataTemplate x:Key="ClassType2">
            <TextBlock Foreground="Firebrick"
                       Text="{Binding DifferentValue}" />
        </DataTemplate>
    </Page.Resources>

    <ListView ItemsSource="{Binding}"
              ItemTemplateSelector="{StaticResource AutoSelector}"
              Padding="40" />
</Page>

Of course there are limitations with this approach, mainly that namespaces cannot be used (i.e. you can’t have the key as local:MyType). This means it is not possible to auto select the template if two types have the same name but live in different namespaces – for my scenario this wasn’t a problem.

Strtod in C# – Part 2: The implementation

The way we’re going to parse the number is from the string is the same way as in “What Every Computer Scientist Should Know About Floating-Point Arithmetic” I linked to last time (note this is for a single precision number, hence nine digits – we’ll need to use more):

First read in the 9 decimal digits as an integer N, ignoring the decimal point. [..] Next find the appropriate power 10P necessary to scale N. This will be a combination of the exponent of the decimal number, together with the position of the (up until now) ignored decimal point. [..] Finally multiply (or divide if P < 0) N and 10|P|.

The style I’ve used to parse the string is a series of static functions that take the string, the current index and return the index of the end of their data, passing any extracted data through an out parameter. In code that looks like this:

private static int SkipWhiteSpace(string str, int index);
private static int ParseSign(string str, int index, out int value);

I could have made the string and index member variables, but if the parsing failed I would need to roll back the index. I also toyed with the idea of using an iterator, but I couldn’t see an advantage. Also, when parsing the significand two values need to be returned to take into account the decimal place. Sure, I could have used a Tuple to accomplish this, put I went for the above to keep everything consistent.

I’m not going to go through each method here (you can download the updated code here) but I’ll go through the main sequence of events.

  • First we validate the arguments. This will be one less worry for the private methods knowing the passed in values are sane.
  • Skip any whitespace, remembering the position of the first non-whitespace character for later.
  • Try to parse a number. This means searching for a sign, skip any leading zeros and then parse the significand. Parsing the significand will give us a number and an exponent, in case the number has a decimal point. If we’ve parsed any digits (including the leading zeros) then we can check for an exponent and adjust the exponent of the significand accordingly. Finally, we can create a double from the sign, significand (stored in a 64-bit integer) and exponent.
  • If we didn’t parse any digits then we need to search for +/- infinity or NaN, after skipping the whitespace.
  • Failing that then we couldn’t get any number so set the end to the starting index and return 0.

It’s actually quite difficult to explain in words, so here’s a code snippet:

public static double Parse(string input, int start, out int end)
{
    if (input == null)
    {
        throw new ArgumentNullException("input");
    }
    if (start < 0)
    {
        throw new ArgumentOutOfRangeException("start", "Value cannot be negative.");
    }
    if (start > input.Length)
    {
        throw new ArgumentOutOfRangeException("start", "Value must be less then input.Length");
    }

    int endOfWhitespace = SkipWhiteSpace(input, start);

    long significand;
    int significandsExponent, sign;
    int startOfDigits = ParseSign(input, endOfWhitespace, out sign);
    int index = SkipLeadingZeros(input, startOfDigits);
    index = ParseSignificand(input, index, out significand, out significandsExponent);

    // Have we parsed a number?
    if ((index - startOfDigits) > 0)
    {
        int exponent;
        end = ParseExponent(input, index, out exponent);
        return MakeDouble(significand * sign, exponent - significandsExponent);
    }

    // Not a number, is it a constant?
    double value;
    end = ParseNamedConstant(input, endOfWhitespace, out value);
    if (end != endOfWhitespace)
    {
        return value;
    }

    // If we're here then we couldn't parse anything.
    end = start;
    return default(double);
}

One thing that caught me out (but picked up in the unit tests) was creating the double from the significand and the exponent when the exponent is less than -308 – there exists a category of floating point numbers that are denormalized so I needed to add a check in the MakeDouble function to handle these, as it was rounding them down to zero.

Strtod in C# – Part 1: The specification

As mentioned, parsing the points in an SVG polygon would be a lot easier (and quicker?) if we had the strtod function in C#. Well, let’s give it a go! Now, dealing with floating point numbers is tricky so I’m probably going to mess it up on some corner cases, so to limit the damage we’re going to create some tests that our function must be able to handle. These tests will also help create our specification, hopefully!

Precision

First of all, how accurate do we have to be? Well, §4.3 states:

a number has the capacity for at least a single-precision floating point number

It also goes on to mention that it’s preferable that double-precision be used for calculations, so we may as well parse to double to aid in calculations, knowing that any value stored in the SVG should fall within a valid range.

So, how many digits are we going to parse? What Every Computer Scientist Should Know About Floating-Point Arithmetic by David Goldberg is by far the best work on trying to understand floating point numbers. I don’t claim to understand it all, however, in the precision section he mentions that 17 digits are enough to recover a double precision binary number. However, that’s not quite correct – 17 significant digits are required, as 12345678901234567 and 000000000012345678901234567 are the same number.

Here’s what we’ll test (also making sure that the whole string is read):


Input Expected
12345678901234567 12345678901234567
000000000012345678901234567 12345678901234567
12345678901234567890 12345678901234567000
1.2345678901234567 1.2345678901234567
0.00000000012345678901234567 0.00000000012345678901234567
1.00000000012345678901234567 1.0000000001234567
1234567890.00000000001234567 1234567890

Underflow/Overflow

What happens when the value is too small (as in very close to zero, not as in a negative number is outside of the valid range) or too large to represent?

System.Double.Parse makes numbers that are too small to be represented by double silently underflow into zero. This also happens when converting a very small double to float. However, if the number is outside the range of double then System.Double.Parse throws a System.OverflowException. This doesn’t make sense to me, especially since casting a big double to float will convert it to infinity. In this situation, strtod returns HUGE_VAL and this is the route I’ll take – numbers that are too big to fit inside the range of a double will be returned as +/- infinity and numbers that are very close to zero that double cannot represent will be truncated to zero.

Therefore, our tests will make sure the following happen (again making sure all input is read):


Input Expected
+4.9406564584124654E-324 4.9406564584124654E-324
+1.7976931348623157E+308 1.7976931348623157E+308
-4.9406564584124654E-324 -4.9406564584124654E-324
-1.7976931348623157E+308 -1.7976931348623157E+308
+1E-325 0
+1E+309 Infinity
-1E-325 0
-1E+309 -Infinity

Infinity/Not a Number

There’s an interesting point to take into consideration when parsing – the SVG specification seems to only allows numbers, yet in XML, INF, -INF and NaN are valid.

When parsing we’ll try to be as flexible as possible, so will allow "Inf", "Infinity" and "NaN" (all case-insensitive).

Valid Formats

The number section of the standard gives the following EBNF grammar for a valid number:

integer ::= [+-]? [0-9]+
number  ::= integer ([Ee] integer)?
            | [+-]? [0-9]* "." [0-9]+ ([Ee] integer)?

What’s interesting about this is that numbers with a trailing decimal point are invalid (i.e 0. doesn’t match the grammar). We’ll assume that’s an oversight and allow it (System.Double.Parse and strtod have no problems with it.) However, we need to be careful that a single decimal point is not parsed.

Testing this is a bit more involved, as strtod will parse as much of the input as it can, so while 0e++0 looks invalid, our function should be able to parse the first zero and then stop when it gets to the e. To test this we therefore need to make sure that our function does not consume the whole string, just the first few characters.

The Code

Think that’s all for now. Here’s the test cases; the actual class will follow later.

Eventually I’d like to allow for different culture settings, but for now I’m concentrating on the SVG spec.

SVG browser resizing

The advantage of using SVG is in its name – Scalable Vector Graphics. You can create your image at whatever size you want and later you can resize it without it getting blocky/blurry etc.

That’s great in theory. I’ve had problems in the past where I would set the logo of a website as a semi-transparent background but the page would centre it instead of scaling it. This quickly led me to use the viewBox property and not the width + height properties.

This led to a problem in webkit based browsers. Turns out you need to provide both – the viewBox and the width + height. See this post for an excellent comparison of SVG content in the different browsers.