The Problem Solver

Tell me and I will forget
Show me and I will remember
Involve me and I will understand
- Confucius -

Google Ads

This Blog

Syndication

Search

Tags

News





  • View Maurice De Beijer's profile on LinkedIn

Community

Email Notifications

Explore

Archives

December 2008 - Posts

In a previous blog post I pointed out that quite a difference between data validation between Silverlight and WFP. As I don’t think adding data validation in the UI is a good thing I focused on validation in the business object by throwing an exception when the value was not acceptable. As Beth pointed out WPF also supports the IDataErrorInfo interface as she demonstrates here.

I think using the IDataErrorInfo interface is superior to throwing exceptions. After all exceptions should be exceptional and users entering invalid data in real applications is not very exceptional  Sad. However Silverlight only contains a subset of the .NET framework and doesn’t include the IDataErrorInfo interface.

So using the IDataErrorInfo in Silverlight will option will not work right?

Wrong, it is a very simple interface and we can just add it ourselves. We can even add it using the same namespace System.ComponentModel to when the interface gets added to Silverlight we can just remove our copy Smile.

So this is my Silverlight implementation of the IDataErrorInfo interface:

namespace System.ComponentModel
{
    // Summary:
    //     Provides the functionality to offer custom error information that a user
    //     interface can bind to.
    public interface IDataErrorInfo
    {
        // Summary:
        //     Gets an error message indicating what is wrong with this object.
        //
        // Returns:
        //     An error message indicating what is wrong with this object. The default is
        //     an empty string ("").
        string Error { get; }

        // Summary:
        //     Gets the error message for the property with the given name.
        //
        // Parameters:
        //   columnName:
        //     The name of the property whose error message to get.
        //
        // Returns:
        //     The error message for the property. The default is an empty string ("").
        string this[string columnName] { get; }
    }
}

I just copied this code by right clicking the IDataErrorInfo in my WPF application and selecting all the code shown.

So how do WPF and Silverlight compare when using the IDataErrorInfo interface?

 

The sample business object is the same person as in the pervious blog post. Only this time I did implement both the IDataErrorInfo and the INotifyPropertyChanged interface. The INotifyPropertyChanged is not really needed in WPF here, it will work just as well without it, but is a good practice to do every time.

public class Person : IDataErrorInfo, INotifyPropertyChanged
{
    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set
        {
            _firstName = value;
            if (string.IsNullOrEmpty(_firstName))
                _errors["FirstName"] = "The first name cannot be empty.";
            else
                _errors["FirstName"] = null;
            OnPropertyChanged("FirstName");
        }
    }

    private string _lastName;
    public string LastName
    {
        get { return _lastName; }
        set
        {
            _lastName = value;
            if (string.IsNullOrEmpty(_lastName))
                _errors["LastName"] = "The last name cannot be empty.";
            else
                _errors["LastName"] = null;
            OnPropertyChanged("LastName");
        }
    }

    private Dictionary<string, string> _errors = new Dictionary<string, string>();
    public string Error
    {
        get
        {
            StringBuilder sb = new StringBuilder();
            foreach (var item in _errors)
                if (item.Value != null)
                    sb.AppendLine(item.Value);

            return sb.ToString();
        }
    }

    public string this[string columnName]
    {
        get
        {
            string result = null;
            _errors.TryGetValue(columnName, out result);

            return result;
        }
    }

    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    public event PropertyChangedEventHandler PropertyChanged;

The WPF application

The XAML in the WPF application is simple, even simpler as previous blog post and looks like this:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="150"/>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <TextBlock Text="Firstname:" Grid.Row="0" Grid.Column="0"/>
    <TextBox Text="{Binding FirstName, ValidatesOnDataErrors=True}" 
             Grid.Row="0" Grid.Column="1"/>
    <TextBlock Text="Lastname:" 
               Grid.Row="1" Grid.Column="0"/>
    <TextBox Text="{Binding LastName, ValidatesOnDataErrors=True}" 
             Grid.Row="1" Grid.Column="1"/>
    <Button Content="Close" Grid.Row="2" Grid.Column="0"/>
</Grid>

Nice, no longer do we need to add the ValidationRules collection and add the ExceptionValidationRule to it, instead all we have to do it set the ValidatesOnDataErrors to true. Much nicer Smile.

image

 

How about the Silverlight application?

The Silverlight XAML isn’t much more complicated and looks like this:

<Grid x:Name="LayoutRoot" Background="White">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="150"/>
        <ColumnDefinition />
        <ColumnDefinition  Width="20"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <TextBlock Text="Firstname:" Grid.Row="0" Grid.Column="0"/>
    <TextBox Text="{Binding FirstName, Mode=TwoWay}" 
             Grid.Row="0" Grid.Column="1"/>
    <local:ErrorStatus PropertyName="FirstName"  Grid.Row="0" Grid.Column="2"/>
    <TextBlock Text="Lastname:" Grid.Row="1" Grid.Column="0"/>
    <TextBox Text="{Binding LastName, Mode=TwoWay}" 
             Grid.Row="1" Grid.Column="1"/>
    <local:ErrorStatus PropertyName="LastName" Grid.Row="1" Grid.Column="2"/>
    <Button Content="Close" Grid.Row="2" Grid.Column="0" Click="Button_Click" />
</Grid>

The main difference is the addition of two local:ErrorStatus elements. Most of the extra complexity is in this control which is needed because Silverlight has no default way to display validation errors. Please note that there is no longer a BindingValidationError handler involved, everything the app needs is done in XAML, much better than the approach when throwing exceptions. Also note that all I need to do is set the PropertyName attribute to indicate which property validation to display. When run this page looks like this:

image

 

The ErrorStatus control

All “magic” happens inside of the ErrorStatus control. This is a real simple user control. Now if I wanted to create a reusable control I would need to put some more work into it and use the VisualStateManager with the States&Parts model but this simple control is enough to demonstrate the solution.

The ErrorStatus.xaml looks like this:

<UserControl x:Class="SilverlightApplication5.ErrorStatus"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="16" Height="16">
    <Grid x:Name="LayoutRoot" >
        <Ellipse Fill="Red"/>
        <TextBlock Foreground="White" 
                   HorizontalAlignment="Center" 
                   VerticalAlignment="Stretch" 
                   FontWeight="Bold" >!</TextBlock>
    </Grid>
</UserControl>

Real simple, just a red circle with a white exclamation mark in it.

The code is not very complex either. Most of it is related to either checking if the DataContext changed, see this post for an explanation, and when a property value has changed.

public partial class ErrorStatus : UserControl
{
    public ErrorStatus()
    {
        InitializeComponent();
        SetBinding(MyDataContextProperty, new Binding());
    }

    public static readonly DependencyProperty MyDataContextProperty =
        DependencyProperty.Register("MyDataContext", 
                                    typeof(object), 
                                    typeof(ErrorStatus), 
                                    new PropertyMetadata(DataContextChanged));

    public static readonly DependencyProperty PropertyNameProperty =
        DependencyProperty.Register("PropertyName",
                                    typeof(string),
                                    typeof(ErrorStatus),
                                    null);

    private static void DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        INotifyPropertyChanged person;
        ErrorStatus errorStatus = (ErrorStatus)sender;

        person = e.OldValue as INotifyPropertyChanged;
        if (person != null)
            person.PropertyChanged -= errorStatus.person_PropertyChanged;

        person = e.NewValue as INotifyPropertyChanged;
        if (person != null)
            person.PropertyChanged += errorStatus.person_PropertyChanged;

        errorStatus.UpdateStatus(e.NewValue);
    }

    public string PropertyName
    {
        get { return (string)GetValue(PropertyNameProperty); }
        set { SetValue(PropertyNameProperty, value); }
    }

    private void person_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == PropertyName)
            UpdateStatus(sender);
    }

    private void UpdateStatus(object sender)
    {
        IDataErrorInfo person = sender as IDataErrorInfo;
        if (person != null)
        {
            string errorText = person[PropertyName];
            if (string.IsNullOrEmpty(errorText))
                Opacity = 0;
            else
                Opacity = 100;

            ToolTipService.SetToolTip(this, errorText);
        }
    }
}

The real work happens in the UpdateStatus() function right at the bottom. This function is called every time the target property changes or the DataContext is set. Basically it checks if there are any errors and makes the control visible or invisible depending on the result. Besides the control’s visibility it also sets the tooltip text to the error. The only other thing worth mentioning is that I make the control invisible by using the Opacity instead of the Visibility property. The reason is that I do not want to change the layout of the controls on the page just because the validation status changed. WPF has a Visibility option of Visibility.Hidden but unfortunately Silverlight doesn’t support this. Not a big problem as making a control transparent is just a good in this case.

Conclusion

Using the IDataErrorInfo is a much nicer approach and creating just one, pretty simple, control in Silverlight makes it work just as easy in Silverlight as WPF. So much better than throwing exceptions Smile

Download the source

Enjoy!

www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu

Posted by Maurice | 7 comment(s)
Filed under: , , ,

The DataContext is a wonderful property, you can set it somewhere in the logical tree and any child control can just bind to properties without having to know where the DataContext was set. A great capability that makes live much simpler when writing XAML. But sometimes when building a control of some sorts you just need to know when the DataContext has changed. For example when binding to events on whatever object is set as the current DataContext.

Take for example the following simple form.

image

In this form I am data bound to a real simple Person object which implements the INotifyPropertyChanged interface so we can be informed that a property has changed. The bottom control is a very simple custom control that displays the last property being changed. The code looks like this:

public partial class MyControl : UserControl
{
    public MyControl()
    {
        InitializeComponent();
        Loaded += new RoutedEventHandler(MyControl_Loaded);
    }

    void MyControl_Loaded(object sender, RoutedEventArgs e)
    {
        INotifyPropertyChanged person = DataContext as INotifyPropertyChanged;
        if (person != null)
            person.PropertyChanged += new PropertyChangedEventHandler(person_PropertyChanged);
    }

    void person_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        PropertyName.Text = e.PropertyName;
    }
}

The Page code looks like this:

public partial class Page : UserControl
{
    public Page()
    {
        InitializeComponent();
        DataContext = new Person() { FirstName = "Maurice", LastName = "de Beijer" };
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        DataContext = new Person() { FirstName = "John", LastName = "Doe" };
    }
}

 

Pretty simple and it works just fine as long as I don’t press the button.

Pressing the button means I set the DataContext to a new person object. The data binding notices and shows the required changes just fine. However the INotifyPropertyChanged event is still hooked on the old person object and we somehow need to unhook this object and hook the new person object.

In WPF there is an DataContextChanged event that will let us know the DataContext is changed and we need to change out event binding. Unfortunately Silverlight the FrameworkElement class in Silverlight has the same event but it is marked as internal so we cannot use it Sad.

So how can we know the DataContext has changed is the event is not public?

It turns out the standard DataBinding holds the answer to the problem. All we need to do is create an extra DependencyProperty and bind that to the DataContext. Sounds complicated but is actually quite simple.

The new version of my custom control is below.

public partial class MyControl : UserControl
{
    public MyControl()
    {
        InitializeComponent();
        SetBinding(MyDataContextProperty, new Binding());
    }


    public static readonly DependencyProperty MyDataContextProperty =
        DependencyProperty.Register("MyDataContext",
                                    typeof(Object),
                                    typeof(MyControl),
                                    new PropertyMetadata(DataContextChanged));

    private static void DataContextChanged(
        object sender, 
        DependencyPropertyChangedEventArgs e)
    {
        MyControl myControl = (MyControl)sender;
        INotifyPropertyChanged person = e.NewValue as INotifyPropertyChanged;
        if (person != null)
            person.PropertyChanged += myControl.person_PropertyChanged;
    }

    void person_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        PropertyName.Text = e.PropertyName;
    }
}

Instead of just reading the DataContext property I first created a new DependencyProperty called MyDataContextProperty. The reason this exists is so we can set the PropertyChangedCallback that lets us know when the property is changed. Note there are no normal property get and set methods as we don’t need them. The remaining and most important part to this to work is the line:

SetBinding(MyDataContextProperty, new Binding());

This line in the constructor actually bind the value of the MyDataContext to the real DataContext property.

With this set up I am free to do whatever I want in the DataContextChanged event that gets fired whenever the DataContext changes. In this example the code just removes the vent handler for the old DataContext PropertyChanged event and adds an event hook on the PropertyChanged event for the new DataContext.

private static void DataContextChanged(
    object sender,
    DependencyPropertyChangedEventArgs e)
{
    MyControl myControl = (MyControl)sender;
    INotifyPropertyChanged person;

    person = e.OldValue as INotifyPropertyChanged;
    if (person != null)
        person.PropertyChanged -= myControl.person_PropertyChanged;

    person = e.NewValue as INotifyPropertyChanged;
    if (person != null)
        person.PropertyChanged += myControl.person_PropertyChanged;
}

 

So all it takes is a few lines of code and we know exactly when the DataContext was changed Smile.

www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu

Posted by Maurice | 4 comment(s)
Filed under: , , ,

In my previous blog post I wrote about creating asynchronous unit tests for Silverlight using the Microsoft Silverlight Unit Test Framework. This asynchronous testing capability that the Microsoft Silverlight Unit Test Framework has in the box lets us create some pretty advanced testing capabilities.

The problem with asynchronous tests.

While the async test pattern is very powerful it also has a drawback. This drawback is that the EnqueueTestComplete() must be executed or the test will never complete and the whole test run will halt. And while the test runner will tell you which test is executing it will not tell you where it is waiting, all it does is just sit there and wait.

Take the following test for example. Because the EnqueueConditional() action always returns false it is never going to end.

[TestMethod]
[Asynchronous]
public void TestThatNeverFinishes()
{
    // Do some asynchronous work

    EnqueueConditional(() => false);
    EnqueueTestComplete();
}

Now a Timeout attribute telling the Microsoft Silverlight Unit Test Framework to abort the test if it takes longer than a predefined amount of time would be nice. In fact there is even a Timeout attribute as part of the Microsoft.VisualStudio.TestTools.UnitTesting namespace but adding the Timeout attribute to a SilverlightTest has no effect Sad

The solution

The solution is not very difficult but it does mean having to check for the timeout ourselves. In fact just adding an Assert to every EnqueueConditional() to make sure we don’t timeout will do the trick just fine. The only downside is that we have to do so in very check. If we change the test to the following the test will timeout, with an error, if it takes to long.

[TestMethod]
[Asynchronous]
public void TestThatNeverFinishes()
{
    DateTime startTime = DateTime.Now;

    // Do some asynchronous work

    EnqueueConditional(() =>
    {
        Assert.IsTrue((DateTime.Now - startTime) < TimeSpan.FromSeconds(10), 
            "Timeout on condition 'return false;'");
        return false;
    });

    EnqueueTestComplete();
}

The result is a “nice” error indicating the test took too long.

image

 

Nice, now if only the Microsoft Silverlight Unit Test Framework would support the Timeout attribute it would be even better.

Enjoy!

www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu

Posted by Maurice | 6 comment(s)
Filed under: , ,
Part 1
Part 2
Part 3
Part 4

This post continues on my previous two post on using the Microsoft Silverlight Unit Test Framework. You can find part 1 here and part 2 here.

In the second blog post I showed how to create a wrapper around the WebClient class, the TestableWebClient, so we can actually test code doing asynchronous web access. The part I didn’t really explain was the unit test itself. The unit test code looked likes this:

[TestClass]
public class FlickrDownloadTest : SilverlightTest
{
    [TestMethod]
    [Asynchronous]
    public void Test1()
    {
        FlickrRequest request = new FlickrRequest(typeof(MockTestableWebClient));

        request.PhotoSearchByUser("97044050@N00", (photo) => EnqueueTestComplete());
    }
    
    [TestMethod]
    [Asynchronous]
    public void Test2()
    {
        int pageCount = 0;
        FlickrRequest request = new FlickrRequest(typeof(MockTestableWebClient));

        request.PhotoSearchByUser("97044050@N00", (photo) => pageCount++);
        EnqueueConditional(() =>
            {
                return pageCount == 5;
            });
        EnqueueTestComplete();
    }
}

There are a couple of things to note here. First of all the test class derives from a base class SilverlightTest. This SilverlightTest enabled all sorts of interesting new things like a TestPanel for doing user interface testing. In this case we are interested in the support for asynchronous behavior and that is included in the WorkItemTest class, one of the parents of the SilverlightTest class.

The second thing to note is that each test is decorated with the Asynchronous attribute. This tells the Silverlight Unit Test Framework that the test isn’t done when the method is finished but some asynchronous actions is taken. So when is the test finished? Well as soon as the EnqueueTestComplete() function is called. In the first test this is done as soon a a photo is downloaded in the PhotoSearchByUser() function. The second test does a bit of extra work. It counts the number of photo’s downloaded, the same as the number of pages in this test. The test checks the number of pages downloaded using the EnqueueConditional() call. This EnqueueConditional() takes a lambda expression and waits for the expression to be valid. In this case the test is for the number of pages downloaded. Only when the condition is met do we move on to the next queued command, in this case the EnqueueTestComplete() to indicate that the test is done.

Besides the two methods used so far, the EnqueueTestComplete() and the EnqueueConditional() there are a number of other methods you can use to fine tune the test behavior. The EnqueueCallback() function can be used to add any code to the test queue. Use this to do Assert calls to validate the state of the test. The EnqueueDelay() is another useful function, specially when doing UI testing, to make sure different queued callbacks are not executed to quickly after each other.

Conclusion

The asynchronous testing capability is a great addition to the standard testing capabilities. In normal unit test the same behavior can be achieved using an AutoResetEvent object but this takes more work so it is nice to see that all the plumbing is taken care of Smile.

Enjoy!

 

Update: Part 1, Part 2, Part 3.

 

www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu

Posted by Maurice | 5 comment(s)

When I am creating business applications validating the data in business objects, and displaying any errors, is always a big deal. Even though WPF and Silverlight both use XAML and support data binding the default way to display errors is quite different. Now I am focusing on validation in the business object here even though WPF has additional capabilities of validating input in the XAML using ValidationRules. While there might be some good reason to validate data directly in the UI in some cases I find it a requirement to validate data inside a business object so the validation is done regardless of the way the business object is configured.

Both with Silverlight and WPF it is possible to create business objects that validate their properties. Unfortunately the normal way to do this is by throwing an exception in the property setter if the validation fails. Now I don't really like this approach, in fact I prefer the approach taken by Rocky Lhotka in CSLA or Paul Stovell in his article about Delegates and Business Objects. But that is a subject for another post, lets first take a look at the out of the box behavior.

The test "business object" I am working with is real simple. In fact so simple that I don't even implement INotifyPropertyChanged, something I recommend you always do. But for the purposes of validation it serves no useful purpose so I left it out. The Person class, used both in WPF and Silverlight looks like this:

public class Person
{
    public string FirstName { get; set; }

    private string _lastName;
    public string LastName
    {
        get { return _lastName; }
        set
        {
            _lastName = value;
            if (string.IsNullOrEmpty(_lastName))
                throw new ArgumentNullException();
        }
    }
}

Pretty simple right, the "business rule" here is that the LastName property cannot be empty.

 

Validation in WPF

The XAML used in the WPF sample looks like this:

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="200" Width="400" >
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="150"/>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <TextBlock Text="Firstname:" Grid.Row="0" Grid.Column="0"/>
        <TextBox Text="{Binding FirstName}" Grid.Row="0" Grid.Column="1"/>
        <TextBlock Text="Lastname:" Grid.Row="1" Grid.Column="0"/>
        <TextBox Grid.Row="1" Grid.Column="1">
            <TextBox.Text>
                <Binding Path="LastName">
                    <Binding.ValidationRules>
                        <ExceptionValidationRule/>
                    </Binding.ValidationRules>
                </Binding>                
            </TextBox.Text>
        </TextBox>
        <Button Content="Close" Grid.Row="2" Grid.Column="0"/>
    </Grid>
</Window>

Not very complex but as we can see there is quite a difference between the FirstName TextBox with no validation and the LastName TextBox which must handle the not empty validation. In order for the UI to know about the validation we need to add the Binding.ValidationRules element and add to that the ExceptionValidationRule. The ExceptionValidationRule basically says that any exception raised during the property setter is a failed validation rule. Not very complicated but it does add quite a bit of XAML just to be able to display the fact that something is wrong. When we run the code and empty the LastName TextBox the result looks like this:

image

The red line around the TextBox indicates that there is some kind of error. Where does the red box come from? Well that is just the default ErrorTemplate used and you are free to change it by setting the Validation.ErrorTemplate property on the TextBox.

 

Validation in Silverlight

The XAML in Silverlight looks somewhat different. The main XAML is pretty much the same but as soon as we get into data binding things look very different. See for yourself:

<UserControl x:Class="SilverlightApplication1.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="150"/>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <TextBlock Text="Firstname:" Grid.Row="0" Grid.Column="0"/>
        <TextBox Text="{Binding FirstName}" Grid.Row="0" Grid.Column="1"/>
        <TextBlock Text="Lastname:" Grid.Row="1" Grid.Column="0"/>
        <TextBox Grid.Row="1" Grid.Column="1">
            <TextBox.Text>
                <Binding Path="LastName" Mode="TwoWay" 
                         NotifyOnValidationError="True" 
                         ValidatesOnExceptions="True" />
            </TextBox.Text>
        </TextBox>
        <Button Content="Close" Grid.Row="2" Grid.Column="0"/>
    </Grid>
</UserControl>

 

This time we need to set the NotifyOnValidationError and ValidatesOnExceptions properties of the binding to true. In WPF these properties don't exist and we used the ValidationRules and ExceptionValidationRule to reach the same effect. So what happens when we run this and clear out the LastName TextBox? Actually the validation fails, the exception is thrown and we don't see anything at all Sad. The reason is that in Silverlight there is no Validation.ErrorTemplate, instead we have to do something to let the user know an error occurred. In order to do so we need to subscribe to the BindingValidationError event that fires as soon as a validation fails. To achieve a similar effect as the WPF application we could use some code like this:

public Page()
{
    InitializeComponent();
    BindingValidationError += new EventHandler<ValidationErrorEventArgs>(Page_BindingValidationError);
}

private Brush _borderBrush = null;
void Page_BindingValidationError(object sender, ValidationErrorEventArgs e)
{
    Control control = (Control)e.OriginalSource;

    if (_borderBrush == null)
        _borderBrush = control.BorderBrush;

    switch (e.Action)
    {
        case ValidationErrorEventAction.Added:
            control.BorderBrush = new SolidColorBrush(Colors.Red);
            break;
        case ValidationErrorEventAction.Removed:
            control.BorderBrush = _borderBrush;
            break;
        default:
            break;
    }
}

Not very complicated but still we need to do so in code. Of course the BindingValidationError event doesn't exist in WPF either so non of this XAML or code would post from Silverlight back to WPF Sad.

The effect is the same as in WPF however and looks like this:

image

 

Conclusion

Validation is quite different in WPF and Silverlight making for non portable XAML and code. However the biggest deal is that validation, at least on the WPF side, is more focused on the UI that the business layer where it should be. And the small part where the validation in the UI is used it is completely focused on exceptions and not in business rules, something far superior. So for any serious business application this subject needs some significant work, just like Rock Lhotka had to do with his CSLA framework.

www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu

Posted by Maurice | 3 comment(s)

Last week logged about using a WrapPanel in a listBox and demonstrated how to get the content to wrap around, read about it here.

Turns out the XAML can be even easier. In the previous post I used a ControlTemplate with a Grid to stop the WrapPanel from just expanding horizontally. Turns out there us an even easier way to do so by disabling the horizontal scrollbar using the ListBox ScrollViewer. The following XAML will do the trick just fine:

<UserControl xmlns:controls="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls"  
             x:Class="SilverlightApplication4.Page"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
             Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="White">
        <ListBox x:Name="DemoList" 
                 ScrollViewer.HorizontalScrollBarVisibility="Disabled">
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <controls:WrapPanel />
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding}" 
                   TextAlignment="Right" 
                   Width="25" />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</UserControl>

Used in combination with the following code:

using System.Linq;
using System.Windows;
using System.Windows.Controls;

namespace SilverlightApplication4
{
    public partial class Page : UserControl
    {
        public Page()
        {
            InitializeComponent();
            Loaded += new RoutedEventHandler(Page_Loaded);
        }

        void Page_Loaded(object sender, RoutedEventArgs e)
        {
            DemoList.ItemsSource = Enumerable.Range(1, 250);
        }
    }
}

it produces this Silverlight page:

image

We even get some keyboard support with the new XAML although I am not quite sure if I am happy about that or not. Selecting an element and pressing the down arrow key makes the selection move to the right. Makes sense in that it is the next item in the ItemsSource bit not quite what I was hoping for.

Just for a quick comparison I copied the XAML and code to a WPF application to see what would happen there. Fortunately the only change I hard to make to the ListBox was removing the controls namespace. Great Smile

image

When I ran the same in WPF I do see the keyboard behavior I would like. Pressing the down arrow selects the next item below the current, the same with up and the other arrow keys and even the page up/down scroll a page but move in the same column. Now this is much better behavior!

Enjoy!

www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu

Posted by Maurice | 1 comment(s)
Part 1
Part 2
Part 3
Part 4

In my previous post I described the basic setup of unit testing in Silverlight, you can read all about it here.

The basics where very nice but lots of code we write in Silverlight has to do with networking and in Silverlight that means asynchronous code, something that is always hard to test!

Because, just I like using Flickr, lets download some pictures and see what it takes to make that testable. Below is the very simple application we need to unit test, basically a list of pictures from my Flickr photo stream.

image

Nothing fancy, just a ListBox with pictures Smile

The code in the page is no big deal either and looks like this:

public partial class Page : UserControl
{
    public Page()
    {
        InitializeComponent();
        Loaded += new RoutedEventHandler(Page_Loaded);
    }

    void Page_Loaded(object sender, RoutedEventArgs e)
    {
        PhotoCollection photoCollection = 
            (PhotoCollection)Resources["PhotoCollectionDS"];
        FlickrRequest request = new FlickrRequest();

        request.PhotoSearchByUser("97044050@N00", 
            (photo) => photoCollection.Add(photo));
    }
}

Basically it just retrieves the PhotoCollection, creates a FlickrRequest object and tells it to search for a users photos and add each photo found to the collection. The PhotoCollection is no big deal either and is just a ObservableCollection<Photo>.

The interesting stuff is in the FlickrRequest class. This is the one that needs to be unit tested and looks like this:

public class FlickrRequest
{
    private const string _flickrUrl = "http://api.flickr.com/services/rest";

    public void PhotoSearchByUser(string userId, Action<Photo> action)
    {
        string url = string.Format(
            @"{0}/?method={1}&api_key={2}&user_id={3}&extras=original_format",
            _flickrUrl, "flickr.photos.search", App.FlickrApiKey, userId);

        WebClient client = new WebClient();
        client.OpenReadCompleted += (sender, e) =>
        {
            if (e.Error == null)
            {
                FlickrResponse response = DeserializeResult(e.Result);
                if (response.Status == "ok")
                {
                    foreach (var photo in response.Photos.Photos)
                        action(photo);

                    if (response.Photos.Page < response.Photos.PageCount)
                    {
                        string nextUrl = string.Format("{0}&page={1}", 
                            url, response.Photos.Page + 1);
                        client.OpenReadAsync(new Uri(nextUrl));
                    }
                }
            }
        };

        client.OpenReadAsync(new Uri(url));
    }

    public static FlickrResponse DeserializeResult(Stream stream)
    {
        FlickrResponse response = null;
        try
        {
            XmlSerializer ser = new XmlSerializer(typeof(FlickrResponse));
            response = (FlickrResponse)ser.Deserialize(stream);
        }
        catch (InvalidOperationException)
        {
            response = new FlickrResponse();
        }

        if (response.Photos == null)
            response.Photos = new ResponsePhotoCollection();
        if (response.Photos.Photos == null)
            response.Photos.Photos = new Photo[] { };

        return response;
    }
}

The PhotoSearchByUser function here is the interesting one as it uses the WebClient class and the Flickr REST API to download the photo information. This code also has the complexity that not all the data is returned from the first call but we need to do multiple calls to get all the photo information. Creating a unit test should be straightforward expect for the fact that we do not want to depend on Flickr and fake out the networking parts. After all if we didn’t it would be a integration test instead of a unit test. So we need to somehow fake the networking behavior.

With regular .NET code I use TypeMock to help out with unit testing and I am sure that would make live easy here but unfortunately there is no Silverlight version of TypeMock yet. In fact, as far as I am aware, there is not a single mock framework for use with Silverlight. So we need to do this some other way.

First we need to get rid of the WebClient class because non of its methods are virtual and we cannot substitute another type. So the first thing I did was create a TestableWebClient, which looks just like the original WebClient only it allows me to change the behavior for testing purposes. The TestableWeblient looks like this:

public class TestableWebClient
{
    public event EventHandler<TestableOpenReadCompletedEventArgs> OpenReadCompleted;

    public virtual void OpenReadAsync(Uri address)
    {
        WebClient client = new WebClient();
        client.OpenReadCompleted += (s, e) =>
            {
                OnOpenReadCompleted(e);
            };
        client.OpenReadAsync(address);
    }

    protected void OnOpenReadCompleted(OpenReadCompletedEventArgs e)
    {
        TestableOpenReadCompletedEventArgs args = 
            new TestableOpenReadCompletedEventArgs(e); OnOpenReadCompleted(args); } protected void OnOpenReadCompleted(TestableOpenReadCompletedEventArgs e) { if (OpenReadCompleted != null) { OpenReadCompleted(this, e); } } }

Unfortunately the OpenReadCompletedEventArgs type doesn’t have a public constructor so I cannot create one myself so I have to use a TestableOpenReadCompletedEventArgs instead. This class looks like this:

public class TestableOpenReadCompletedEventArgs : AsyncCompletedEventArgs
{
    public TestableOpenReadCompletedEventArgs(
        Stream result, Exception error, bool cancelled, object userState)
        : base(error, cancelled, userState)
    {
        Result = result;
    }

    public TestableOpenReadCompletedEventArgs(
        OpenReadCompletedEventArgs args)
        : base(args.Error, args.Cancelled, args.UserState)
    {
        Result = args.Result;
    }

    public Stream Result { get; private set; }
}

So with these new classes I can change the PhotoSearchByUser function to use the new class and it now looks like this:

public void PhotoSearchByUser(string userId, Action<Photo> action)
{
    string url = string.Format(
        @"{0}/?method={1}&api_key={2}&user_id={3}&extras=original_format",
        _flickrUrl, "flickr.photos.search", App.FlickrApiKey, userId);

    TestableWebClient client = new TestableWebClient();
    client.OpenReadCompleted += (sender, e) =>
    {
        if (e.Error == null)
        {
            FlickrResponse response = DeserializeResult(e.Result);
            if (response.Status == "ok")
            {
                foreach (var photo in response.Photos.Photos)
                    action(photo);

                if (response.Photos.Page < response.Photos.PageCount)
                {
                    string nextUrl = string.Format("{0}&page={1}", 
                        url, response.Photos.Page + 1);
                    client.OpenReadAsync(new Uri(nextUrl));
                }
            }
        }
    };

    client.OpenReadAsync(new Uri(url));
}

Not much changes, in fact only a single line changed but we are not quite there yet. We still need a way to get our unit tests to use a different TestableWebClient implementation. Do do so I will pass in the type of TestableWebClient to use with the FlickrRequest constructor. Check the new code:

public class FlickrRequest
{
    private string _flickrUrl = "http://api.flickr.com/services/rest";
    private Type _webClientType = typeof(TestableWebClient);

    public FlickrRequest()
    {
    }

    public FlickrRequest(Type webClientType)
    {
        _webClientType = webClientType;
    }

    public void PhotoSearchByUser(string userId, Action<Photo> action)
    {
        string url = string.Format(
            @"{0}/?method={1}&api_key={2}&user_id={3}&extras=original_format",
            _flickrUrl, "flickr.photos.search", App.FlickrApiKey, userId);

        TestableWebClient client = (TestableWebClient)
            Activator.CreateInstance(_webClientType); // Rest of the code left out. } }
Now we can start testing this code Smile

I created two unit tests for this code as an example, they look like this:

[TestClass]
public class FlickrDownloadTest : SilverlightTest
{
    [TestMethod]
    [Asynchronous]
    public void Test1()
    {
        FlickrRequest request = new FlickrRequest(typeof(MockTestableWebClient));

        request.PhotoSearchByUser("97044050@N00", (photo) => EnqueueTestComplete());
    }
    
    [TestMethod]
    [Asynchronous]
    public void Test2()
    {
        int pageCount = 0;
        FlickrRequest request = new FlickrRequest(typeof(MockTestableWebClient));

        request.PhotoSearchByUser("97044050@N00", (photo) => pageCount++);
        EnqueueConditional(() =>
            {
                return pageCount == 5;
            });
        EnqueueTestComplete();
    }
}

The fake, or mock, WebClient looks like this:

public class MockTestableWebClient : TestableWebClient
{
    private int _page = 0;

    public override void OpenReadAsync(Uri address)
    {
        _page++;

        FlickrResponse response = new FlickrResponse();
        response.Status = "ok";
        response.Photos = new ResponsePhotoCollection();
        response.Photos.Page = _page;
        response.Photos.PageCount = 5;
        response.Photos.Photos = new Photo[] { new Photo() };
        Stream stream = SerializeResult(response);
        stream.Position = 0;
        TestableOpenReadCompletedEventArgs args = 
            new TestableOpenReadCompletedEventArgs(stream, null, false, null);
        OnOpenReadCompleted(args);
    }


    public static Stream SerializeResult(FlickrResponse response)
    {
        MemoryStream stream = new MemoryStream();
        XmlSerializer ser = new XmlSerializer(typeof(FlickrResponse));
        ser.Serialize(stream, response);

        return stream;
    }
}

Basically I just return a response stating that there are 5 pages and each contains a single blank photo.

Running these tests produces the following output showing both tests passed Smile

image

 

Am I happy with the changes I had to make to the Silverlight app to make it unit testable? Well yes and no. I didn’t like having to create a wrapper class for the WebClient and the OpenReadCompletedEventArgs. Bit now that I have done so creating using other test for code using the WebClient is a lot easier. In this case I only added the OpenReadAsync() function but doing the same with the other functions is a breeze. And the end result is I could unit test the code in PhotoSearchByUser() pretty much the way I wrote it without having to change the code a lot just to make it unit testable and that is good! So overall I am reasonably happy with the result Smile

I pretty much skipped all details of the actual unit testing code itself. Now there is some new stuff so in a future blog post I am going to explain what I did in the unit tests themselves.

And thanks to Jeff Wilcox for providing some useful feedback.

Enjoy!

 

Update: Part 1, Part 2, Part 3.

 

www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu

Posted by Maurice | 9 comment(s)

A while a go I wrote some posts about unit testing Windows Workflow foundation Activities, you can find the posts here and here. Fortunately I am not the only one who thinks unit testing is important as you can find various other blog posts about it like this one from Ron Jacobs.

But Cliff Simpkins has taken this one step further and just blogged about a new MSDN virtual lab "Using Test-First Development with WF"! Excellent work and I recommend doing the lab, I know I did! And while you are at it, there are a  number of other interesting labs you can do.

 

Read more about Cliffs announcement here or go straight to the lab here.

Enjoy!

www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu

Posted by Maurice | 1 comment(s)
Filed under: , , , ,
Part 1
Part 2
Part 3
Part 4

Unit testing is an important part of daily life for a developer and with good reason. After all unit testing software makes it easier to make changes and change is the only constant in software development!

With regular .NET code you can right click on a class and select “Create Unit Tests” to get started. Unfortunately with Silverlight that just shows the following empty dialog.

image

The reason being that Silverlight source code is compiled against a different runtime and Visual Studio 2008 doesn’t know how to run those tests. Fortunately the Silverlight Toolkit released here on CodePlex also contains the Silverlight unit testing framework Microsoft uses to build these controls.

Using this framework we can start building our own unit tests for Silverlight code.

Getting started is easy.

First create a new Silverlight project and name it SilverlightTest1 and a the following class to it:

 

using System;
using System.Windows;
using System.Windows.Media.Imaging;

namespace SilverlightTest1
{
    public class Photo
    {

        public string Title { get; set; }
        public string Url { get; set; }
        public double Height { get; set; }
        public double Width { get; set; }
        public Size Size
        {
            get
            {
                return new Size(Width, Height);
            }
        }

        public BitmapImage getImage()
        {
            BitmapImage image = new BitmapImage(new Uri(Url));
            return image;
        }
    }
}

This is the code we are going to test.

Next add a second Silverlight project to the solution. Name this one SilverlightTest1Tests and select the option to automatically generate a test page like this.

image

This is going to be the project that contains our test cases.

Next we need to add references to the project we are going to test and the two assemblies containing the test framework: Microsoft.Silverlight.Testing.dll and Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight.dll. These two DLL’s can be found in the folder where you unpacked the SilverlightToolkit_Nov08_Source.zip in the Source\Binaries folder.

image

We will not be using the Page1.xaml in the SilverlightTest1Tests project so go ahead and delete it. Instead we are going to use a root page generated by the test system. In order to use this open the App.xaml.cs file and locate the Application_Startup function. Here we are going to change the RootVisual like this:

 

private void Application_Startup(object sender, StartupEventArgs e)
{
    this.RootVisual = UnitTestSystem.CreateTestPage();
}

Now we can run this project. Doing so will give the following output:

image

Not all that interesting yet as there where no test cases yet.

So lets add out first unit test!

Right click the project and add a new class named PhotoTest and add the following code:

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace SilverlightTest1Tests
{
    [TestClass]
    public class PhotoTest
    {
        [TestMethod]
        public void Test1()
        {
            Assert.IsTrue(true);
        }
    }
}

Now rerun the SilverlightTest1Tests project and the browser should look like this:

image

Nice out first test Smile

Lets add some more. The code below are some more tests:

[TestMethod]
public void PhotoCreator()
{
    Photo photo = new Photo();
}

[TestMethod]
public void PhotoSize()
{
    Photo photo = new Photo();
    photo.Height = 256;
    photo.Width = 128;

    Assert.AreEqual(256, photo.Size.Height);
    Assert.AreEqual(128, photo.Size.Width);
}

[TestMethod]
public void GetNullImage()
{
    Photo photo = new Photo();
    var image = photo.GetImage();
}

 

One useful trick is leave the browser with the test page open. That way we can just rebuild the project and hit refresh in the browser. If I do I end up with the following output:

image

Clearly something is wrong as the GetNullImage test is failing. This was actually expected because I never set the Url for the photo so we cannot retrieve the image. So we need to tell the test framework this was the expected outcome. So change the GetNullImage test to the following:

[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void GetNullImage()
{
    Photo photo = new Photo();
    var image = photo.GetImage();
}

The ExpectedException attribute tells the unit test system that an ArgumentNullException is supposed to be thrown. In fact the test will fail now if the exception is not raised. Rebuild and refresh the browser to see the following output:

image

Clearly all test run just fine again Smile

 

Looking for more information on Silverlight unit testing? Then take a look at Jeff Wilcox blog posts here or Jonas Follesø here.

Enjoy!

 

Update: Part 1, Part 2, Part 3.

 

www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu

Posted by Maurice | 9 comment(s)
Filed under: , ,