How To Refactor And Build Better Microsoft Silverlight Applications

As with all development technologies if you asked two developers how to solve a problem it’s unlikely both would come up with the same solution.

It’s no surprise then the same solution to a problem using Silverlight and WPF applications can be implemented in a number of ways.

In a series of posts I want to show how we can refactor a Silverlight application which “works” to be a lot cleaner, easier to maintain and adheres to good development practices.

Although I’m using Silverlight many of the changes and suggestions would also apply to a WPF application.

So what’s the application?

The application adds two numbers together.

Silverlight Calculator

Yes that’s it. Click here to see a live demo of the calclator.

Using a simple example (as opposed to a huge complex monster) allows us to focus on refactoring and making improvements rather than trying to understand what the application is doing and wading through hundreds of lines of code.

So what’s wrong with it?

The XAML is shown below

    <Grid x:Name="LayoutRoot" Background="White" Height="100" Width="350">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBox Grid.Column="0" Text="0" Height="25" TextAlignment="Right" x:Name="tbFirstValue"/>
        <TextBlock Grid.Column="1" Text="+" Height="25" TextAlignment="Center"/>
        <TextBox Grid.Column="2" Text="0" Height="25" TextAlignment="Right" x:Name="tbSecondValue"/>
        <TextBlock Grid.Column="3" Text="=" Height="25" TextAlignment="Center"/>
        <TextBlock Grid.Column="4" Text="0" Height="25" TextAlignment="Left" x:Name="tbResult"/>
        <Button Grid.Row="1" Grid.ColumnSpan="5" Margin="0,5,0,0" Content="Calculate" x:Name="btnCalculate" Click="btnCalculate_Click" />
    </Grid>

and this is what the code behind looks like

public partial class MainPage : UserControl
{
    public MainPage()
    {
        InitializeComponent();
    }

    private void btnCalculate_Click(object sender, RoutedEventArgs e)
    {
        tbResult.Text = (Convert.ToInt32(tbFirstValue.Text)  + Convert.ToInt32(tbSecondValue.Text)).ToString();
    }
}

As it stands the application:

  • Contains code in the code behind file. OK it’s not so much of an issue for this example and is down to individual preference, but this can quickly become a nightmare to maintain during the life of an application
  • Isn’t unit testable – we can’t test two values can be added together
  • Has no separation of concerns – the code behind shouldn’t be responsible for adding the numbers together
  • A lot of repetition for the styling of the input boxes – if we wanted to make the input boxes bigger we would have to make multiple changes, ideally changes should only need to be made in one place.
  • No validation – if the user enters alphabetical characters into application and hits the calculate button the application crashes

So how are we going to improve it?

By taking an agile approach the aim at the end of each refactoring is to have a releasable application i.e. be able to add two numbers together. Therefore each refactoring will involve small incremental changes.

After each refactoring exercise we will review the application to see what improvements have been made and if any new problems have been introduced…

WPF and Silverlight Value Converter Example in VB and C#

In this post I want to show how a value converter in Silverlight and WPF can be used to output the value of a slider control.

The code used in this post downloaded here.

Why Are Value Converters Useful?

In the screen shot below you can see a slider control and two numbers representing its value. As you can see the value not using a converter is somewhat lacking in its visual appeal and isn’t user friendly.

Silverlight Value Converter Example

The XAML used to create this is shown below

<UserControl x:Class="ValueConverterExample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:ValueConverterExample" mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="500">
    <UserControl.Resources>
        <local:SliderValueConvertor x:Key="SliderValueConvertor"/>
    </UserControl.Resources>

    <Grid x:Name="LayoutRoot" Background="White" Height="Auto" Width="500" Margin="0,50,0,0">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="4*"/>
            <ColumnDefinition Width="3*"/>
            <ColumnDefinition Width="3*"/>
        </Grid.ColumnDefinitions>

        <TextBlock Grid.Column="1" Text="Without a Convertor" Margin="5" HorizontalAlignment="Center"/>
        <TextBlock Grid.Column="2" Text="With a Convertor" Margin="5" HorizontalAlignment="Center"/>
        <Slider x:Name="mySilder" Grid.Row="1" Minimum="0" Maximum="10" Margin="5" SmallChange="1" />
        <TextBlock x:Name="txtBlkWithoutConverter" Grid.Row="1" Grid.Column="1" Text="{Binding ElementName=mySilder, Path=Value}" VerticalAlignment="Center"  HorizontalAlignment="Center"/>
        <TextBlock  x:Name="txtBlkUsingConverter" Grid.Row="1" Grid.Column="2" Text="{Binding ElementName=mySilder, Path=Value, Converter={StaticResource SliderValueConvertor}}" VerticalAlignment="Center"  HorizontalAlignment="Center"/>
    </Grid>
</UserControl>

Note how in the text binding for the txtBlkUsingConverter text block a SliderValueConvertor is used.

The code for the value converter looks like this in VB

Public Class SliderValueConvertor
	Implements IValueConverter
	Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object
		Return Math.Round(CDbl(value))
	End Function

	Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object
		Return Nothing
	End Function
End Class

and like this in C#

public class SliderValueConvertor : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return Math.Round((double) value);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return null;
    }
}

By implementing the IValueConverter interface the slider value can be rounded to show a whole number. There’s no need to support the ConvertBack method because the text block isn’t editable.

I could have done this using code behind…

Yes if you created a handler for the slider value changed event in the code behind it’s possible to achieve the same result. But I find this solution much cleaner and can be used if you’re implementing the MVVM pattern.

How to Convert a SketchFlow Prototype into a Production Application… And why you shouldn’t!

One of the first questions I’m getting asked after my SketchFlow presentation is about converting a SketchFlow prototype to a production application.

Now before I answer this question, I know some of you may have arrived here from a search engine, so if you want a solution check out the MSDN article on converting into a production project in 16 steps but just because you can it doesn’t mean you should!

SketchFlow Prototype showing the text convert or not to convert.  That is the question.

One of the problems with prototyping tools like SketchFlow is they can sometimes leave your client with the impression that all the work is done the and product is in some way releasable or production ready.

Now I’m not saying nothing can be shared between the two solutions (e.g. resources) because that depends on the design and project you are working on.

What is clear however are the aims and mindsets used to create a SketchFlow prototype are different from how you would go about creating a real world production solution.

From a design perspective the layout of controls in SketchFlow are done using a single grid and their margin property. In a real world application you would pay more consideration into the layout of the design and think about things like how the page would scale.

From a developer perspective a SketchFlow prototype doesn’t easily lend itself to good development practices such as SOLID design principles, code reusability and testing.

And in any case would you really deploy files called something like Screen_1.xaml to a production server?

Even if these things don’t matter to you, I still don’t recommend using Microsoft’s solution because

  • there are still references to the Microsoft.Expression.Protyping libraries in a supposedly production ready solution. Having libraries in your application that you not sure are being used before you launch will only get worse as time goes on.
  • Microsoft’s solution is not 100% successful, lots of people are having problems with navigation not working properly.

So what should I do?

  • Focus on creating designs that satisfy the customers’ requirements and not about the final design. You can think what resources could be reused later in the prototyping cycle.
  • Deliver prototypes to your customers early and often. This will allow your customer to give feedback early so you can inspect and adapt.
  • Keep your screen designs simple and lightweight so changes can be done quickly and with the knowledge that you won’t be breaking anything.
  • Keep an eye on how many events and behaviors are used on a control or screen. It’s too easy to get carried away remember it’s only supposed to be a prototype.
  • Take advantage of the sample data resources available and not bind to databases or web services.
  • Keep code behind to a minimum, ideally having none at all.

Jag Reehal’s Final Thought on ‘Converting a SketchFlow Prototype into a Production Application’

I can understand why people are looking for a solution where they can use a prototype and a production application interchangeably because like documentation prototypes can easily get out of date and no longer reflect the design used in the production version. Unfortunately the only answer is to adhere to good practices and always start by prototyping and not by retrospectively making your prototype match your production design.

Prototypes are extremely useful… as prototypes and nothing more!

Have fun using SketchFlow I love it, and it’s definitely my prototyping tool of choice.

Page 5 of 512345