on Dec 15th, 2008StaffWars.fm Preview

Yesterday me and my good friend Jamie won the last.fm Hack Day with our application - StaffWars.fm. We coded the entire application from scratch in just 7 hours while enjoying a free bar. Given that we were possibly drinking heavily the application is a little rough around the edges but we’ll hopefully get something out there which is usable soon. So what does it do? We’ll explain in detail later but for the time being lets just say don’t you hate it when that person in your office insists on playing Mariah Carey repeatedly on the office stereo? Me too.

StaffWars.fm Preview

on Dec 5th, 2008Silverlight JavaScript Value Converter

Value converters allow you to modify the value of the source property of a binding before it is applied to the target. As shown in my previous WPF examples, you would normally write a new class implementing the IValueConverter interface which will do the conversion. For simple transforms such as performing basic arithmetic or formatting a string writing a whole new class can feel like overkill. In WPF a nice way of doing simple transformations on bindings is to use the EvalBinding but unfortunately, there is not a version for Silverlight and due to the lack of Markup Extensions it is difficult to create anything similar.

This became a particular problem in a recent Silverlight project where we were using loose XAML to enable different themes per client for portions of the application and could not know all the possible conversion required in advance. I wanted to be able to use some kind of scripting to express how the binding’s value should be modified and to have this all expressed in XAML. I’ve recently seen a few folks using IronPython scripts inside their .NET applications to enable scripting at runtime and I’ve also used Boo in the past to achieve similar functionality. Both of these options would involve bundling their respective libraries to the client which when we’re writing a consumer facing Silverlight application - the extra weight doesn’t seem very attractive.

Of course why bother including a whole new scripting language in your Silverlight application when you’ve already got one? Silverlight applications are more than likely run from inside a browser which can already run JavaScript. Using this we can create a Value Converter which will use a JavaScript function to perform the transformation in the binding.

<TextBlock>
    <TextBlock.Text>
        <Binding Source="{StaticResource Message}" Converter="{StaticResource ScriptConverter}">
            <Binding.ConverterParameter>
                <sys:String>
                    var t = '';
                    for (var i = 0; i &lt; value.length; i++) {
                        t += value.charAt(value.length - 1 - i);
                    }
                    return t;
                </sys:String>
            </Binding.ConverterParameter>
        </Binding>
    </TextBlock.Text>
</TextBlock>

This example will take convert the bound value, "foobar", and run the javascript specified passing in the value of the Binding as the variable named ‘value’. For readers not familiar with Javascript the example will reverse the text, so that "foobar" becomes "raboof" when displayed in the TextBlock. The syntax is a little strange to look at. Because we’re specifying the script we have to use the full definition of the Binding instead of the common inline attribute syntax. Silverlight does not support CData sections so any invalid characters in XML such as the less than comparison in the for statement has to be escaped.

Calling out to the browser to execute the supplied function is surprisingly easy; we simply create the method and invoke it with the value. The body of the ValueConverter only contains 5 lines of code.

public class ScriptValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        // Format a JSON definition with the converter body making up the function
        var json = "( { 'convert': function(value) { " + parameter.ToString() + "} } )";
        // Create the javascript object
        var o = (ScriptObject)HtmlPage.Window.Eval(json);
        // Get a reference to the Javascript conversion function
        var convertFunction = (ScriptObject)o.GetProperty("convert");
        // Invoke the function with the value to convert from
        var convertedValue = convertFunction.InvokeSelf(value);

        return convertedValue;
    }

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

ScriptValueConverter

I should point out that I haven’t given much thought to performance or security in this example, before using Javascript for your conversions you should think thoroughly about where the script is coming from and how often it will be updated. There is also no error handling so a badly written conversion function will likely tear down your entire application.

Download a sample project here.

on Aug 30th, 2008Change the Default Font of a WPF Application

Introduction

When you create a new application in WPF all text will be displayed using the default font of your operating system. If you’re running Vista the default font will be ‘Segoe UI’, if you’re running on XP I expect it will be Tahoma.

WPFDefaultFontBefore 

Where does the Default Font come from?

There are two main controls which display text in WPF; the TextElement and TextBlock. Both of these controls have a FontFamily property which is backed by a FontFamilyProperty DependencyProperty. We’ll start by looking at the FontFamilyProperty on the TextElement class and how that gets it’s default value.

public static readonly DependencyProperty FontFamilyProperty =
	DependencyProperty.RegisterAttached(
		"FontFamily",
		typeof(FontFamily),
		typeof(TextElement),
		new FrameworkPropertyMetadata(
			SystemFonts.MessageFontFamily,
			... Lots of options ...
		new ValidateValueCallback(IsValidFontFamily));

The default value of a DependencyProperty is taken from the Property Metadata supplied when it is registered. In this case the TextElement is being given the default value of SystemFonts.MessageFontFamily which I assume WPF is reading from the host operating system.

The TextBlock is slightly different, it uses the FontFamily property for the same purpose as the TextElement so instead of declaring a new DependencyProperty it just reuses the existing one from the TextElement.

public static readonly DependencyProperty FontFamilyProperty =
	TextElement.FontFamilyProperty.AddOwner(typeof(TextBlock));

This essentially copies the DependencyProperty which was registered on the TextElement and takes the defaults as well as it’s other associated metadata along with it.

Changing the Default Font

The value of a DependencyProperty is determined by a large number of different factors which are evaluated in an order of precedence. At the very bottom is the default value given to the DependencyProperty when it was registered, this is ideally what we would like to change. We are able to specify new PropertyMetadata using the OverrideMetadata method of a DependencyProperty, my first concern with this method is that we would lose the values specified by the framework for the options but this method is clever enough to merge in the new metadata to what was supplied previously. Using the code below we can specify new defaults for the FontFamily of the TextElement and TextBlock controls ensuring that all Text displayed in our application will now use everyone’s favourite font.

TextElement.FontFamilyProperty.OverrideMetadata(
typeof(TextElement),
new FrameworkPropertyMetadata(
    new FontFamily("Comic Sans MS")));

TextBlock.FontFamilyProperty.OverrideMetadata(
typeof(TextBlock),
new FrameworkPropertyMetadata(
    new FontFamily("Comic Sans MS")));

WPFDefaultFontAfter

Limitations of this Technique

In the above image you’ll see that we’ve successfully change the font on the text blocks, labels and buttons. Unfortunately the font inside the TextBox remains unchanged, this is due to it receiving it’s FontFamily property from it’s base class Control. Control adds itself as an Owner of the TextElement FontFamilyProperty but specifies it’s own metadata which we are then unable to override. In this case our only option is to specify a value for the property higher up the DependencyProperty evaluation chain, for example by creating a implicit style for the Control type.

on Aug 10th, 2008Pluralizing Value Converter

I often find myself wanting to pluralize text in my applications such as displaying either ‘1 Message’ or ‘2 Messages’. Anyone who has played with Rails will have likely came across the Infector which, among other things, is capable of taking a singular word and returning its plural - message => messages and mouse => mice. Fortunately us in the .NET world can take advantage of the functionality with Infector.NET, a port of the Rails Infector by Andrew Peters. Using this I could simply set the value of my label in code;

messageTextBlock.Text = messages.Count == 1 ? "Message" : Inflector.Pluralize("Message");

A potential down side of this technique is that it won’t cope with the value changing, I would by some means have to handle a changed event and re-run the above code. More problems are that I would have to handle this for every bit of text I wanted to pluralize and I’ve now got the text defined in my code instead of the XAML where I’d ideally be setting the text. So with the awesomeness of WPF Data Binding isn’t there a better way of doing this? Of there is.

Bindings can be assigned a ValueConverter which can modify the value from the data source before being set on the target property. In my case I want to bind to a number and display different text dependent on it’s value. A good question is where do we get this text from, fortunately the Binding object has a ConverterParameter property which will be supplied to the ValueConverter when invoked. Using this the implementation of a PluralizingValueConverter is extremely simple.

public class PluralizingValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var number = (int)value;
        var text = (string)parameter;

        // No need to pluralize if there's only one
        if (number == 1)
            return text;

        return Inflector.Net.Inflector.Pluralize(text);
    }

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

I’ve thrown together an example application which has a simple NumericTextBox I knocked up earlier that exposes a integer Value property. I then have a TextBlock binding it’s Text to the Value of the NumericTextBlock, this binding uses the PluralizingValueConverter and supplies the text it wants to display as a ConverterParameter.

<Window x:Class="PluralizationExample.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:PluralizationExample"
    Title="Pluralization Example" Height="300" Width="300">
    <Window.Resources>
        <local:PluralizingValueConverter x:Key="pluralizingConverter" />
    </Window.Resources>
    <StackPanel>
        <StackPanel Orientation="Horizontal">
            <local:NumericTextBox x:Name="numberTextBox" Width="30" Value="3" />
            <TextBlock Text=" blind " />
            <TextBlock Text="{Binding ElementName=numberTextBox, Path=Value, Converter={StaticResource pluralizingConverter}, ConverterParameter='Mouse'}" />
        </StackPanel>
    </StackPanel>
</Window>

As the value of the numeric text is initialised to 3 the application will display the text ‘3 Blind Mice’ when it starts. As expected, changing the value to 1 will cause the text to update which will then read ‘1 Blind Mouse’. Neat.

Mice Mouse

The Inflector class contains a number of other useful methods; such as the Ordinalize method which takes an integer and returns a string of it’s position such as 1 => "1st" and 2 => "2nd". As with Pluralize it is simple to wrap these in ValueConverters to create a more human interface with very little leg work.