# Monday, 02 March 2009

Shaun posted a nice concise example of replacing JavaScript code with similar compiled code in Silverlight.  If you have any complex business logic currently written in JavaScript, this would be a great way of turning that into compiled, type-safe C#.

Monday, 02 March 2009 15:08:15 (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 

After reading Justin Angel’s very good summary of unit testing Silverlight using the Silverlight UnitTest framework, RhinoMocks, Unity etc. I decided to give it a go and find out how easy it was for a “real” application.  I converted the course evaluation app I’ve been working on since December to MVVM using Unity, and then set about trying to test it with the testing tools. 

I must say I do rather like the MVVM pattern, so that part went pretty well, as did the use of Unity, although there was some learning to do there.  It’s not quite as obvious as it maybe should be, but it didn’t take too long.  The biggest issue I had with both Unity and the test tools come in relation to the WCF proxy that I’m using to talk back to the server from Silverlight.  I think it would be a bit easier using the asynchronous interface that is generated as part of the proxy (the one that has all the BeginXXX, EndXXX methods on it) but I’m using the interface that consists of completion events and XXXAsync methods.  That object (in my case it’s called “EvalServiceClient”) doesn’t like being created by Unity, presumably somewhere down in the WCF infrastructure, so I had to create it myself and register the instance with Unity.

Current = new UnityContainer();
Current.RegisterInstance(typeof(EvalServiceClient), new EvalServiceClient());

That isn’t too terrible, but it did take a while to figure out.  One of the things that makes that harder is that the errors that come back just say “Unity couldn’t create your thing” and it takes a bit of digging to find out where and why it actually failed. 

The blogosphere suggests (and I agree) that implementing MVVM in Silverlight isn’t quite as straightforward as it might be in WPF, largely due to the lack of commands.  There are a couple of declarative solutions for mapping UI elements to methods in a View Model, but most relied on quite a bit of infrastructure.  I decided it was OK (enough) to put just enough code in my code-behind to wire up event handlers to methods on the View Model.  Icky?  No too bad.  Commands would obviously be better, but there it is. 

private void submitEval_Click(object sender, RoutedEventArgs e)
{
    ViewModel.SubmitEval();
}

private void lstCourse_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    CourseInfo ci = lstCourse.SelectedItem as CourseInfo;
    ViewModel.CourseSelected(ci);
}

I found that the reliance on data binding makes it much easier to separate presentation from business logic.  The View Model can represent any UI specific logic like which buttons should be enabled when (which the underlying business/domain model doesn’t care about) and allow a designer to work strictly with XAML.  Because INotifyPropertyChanged really works, you don’t have to worry about pushing data into the interface, just on which properties have to be marked as changed.  For a computed property like “should the submit button be shown” it may take a few extra notification calls to make sure the UI gets updated properly, but that seems reasonable. 

public bool CanSubmit
{
    get
    {
        _canSubmit = (_registrationId.HasValue && _questionCategories != null);
        return _canSubmit;
    }
    set
    {
        if (_canSubmit != value)
        {
            _canSubmit = value;
            Changed("CanSubmit");
        }
    }
}

public int? RegistrationId
{
    get
    {
        return _registrationId;
    }
    set
    {
        if (_registrationId != value)
        {
            _registrationId = value;
            Changed("RegistrationId");
            Changed("CanSubmit");
        }
    }
}

public System.Collections.ObjectModel.ObservableCollection<Evaluation.EvaluationServer.QuestionCategory> QuestionCategories
{
    get
    {
        return _questionCategories;
    }
    set
    {
        if (_questionCategories != value)
        {
            _questionCategories = value;
            Changed("QuestionCategories");
            Changed("CanSubmit");
        }
    }
}

In the example above, the value of “CanSubit” relies on the state of RegistrationID and QuestionCategories, so the property setters for those properties also “invalidate” CanSubmit so the UI will update properly.  In the XAML, the IsEnabled property of the Submit button is bound to the CanSubmit property of the View Model.

The next challenge was getting the test code to work.  Because I didn’t want the test code to call the real web service, I had to mock the calls to the EvalServiceClient.  For whatever reason, I didn’t have any luck with mocking the object itself.  I think this had to do with the asynchronous nature of the calls.  The code registers an event handler for each completion event, then calls XXXAsync to call the web service.  When it returns, it fires the completion handler.  To make that work with RhinoMocks, you have to record the event hookup, then capture an IEventRasier interface that will let you raise the desired event.

using (mocks.Record())
{
    client.GetStudentNameCompleted += null;
    raiser = LastCall.IgnoreArguments().GetEventRaiser();

That call to GetEventRaiser fails if I mock the EvalServiceClient object itself, so I had to create an interface that I could mock instead.  Luckily, the generated proxy is a partial class, so it’s easy to add a new interface.

public interface IEvalServiceClient
{
    event System.EventHandler<GetStudentNameCompletedEventArgs> GetStudentNameCompleted;

    void GetStudentNameAsync();
}

public partial class EvalServiceClient : IEvalServiceClient
{

}

Now the RhinoMocks code mock the IEvalServiceClient interface, and the GetEventRaiser call works just fine.  Because the WCF client actually gets created by Unity, we have to register the new mock instance with the UnityContainer.

MockRepository mocks = new MockRepository();
IEvalServiceClient client = mocks.StrictMock<IEvalServiceClient>();

IoC.Current.RegisterInstance<IEvalServiceClient>(client);
IEventRaiser raiser;

using (mocks.Record())
{
    client.GetStudentNameCompleted += null;
    raiser = LastCall.IgnoreArguments().GetEventRaiser();

    client.GetStudentNameAsync();

}

using (mocks.Playback())
{
    Page page = new Page();
    raiser.Raise(client, new GetStudentNameCompletedEventArgs(new object[]{"Jones, Fred"}, null, false, null));
    WaitFor(page, "Loaded");
    TestPanel.Children.Add(page);

    EnqueueCallback(() => Assert.IsTrue(page.lblStudent.Text == "Jones, Fred"));

    EnqueueTestComplete();
}

During playback, we can use the IEventRaiser to fire the completion event, then check the UI to make sure the property got set correctly. 

I’m pretty convinced that MVVM is a good idea, but this method of testing seems awfully cumbersome to me, plus pretty invasive.  I had to make quite a few changes to my app to make the testing work, including creating the interface for the EvalServiceClient, and marking any controls I needed to write tests against with x:FieldModifier=”public” in my XAML.  It’s good to know how to make this work, but I’m not sure I’d use this method to test everything in my Silverlight app.  Probably only the highest risk areas, or places that would be tedious for a tester to hit.

Monday, 02 March 2009 14:42:25 (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, 20 February 2009

On Wednesday I posted about coming up with a way of decorating any UIElement with a red border in response to a validation error.  The only drawback (that I could see just then) was that I had to add borders to all the elements that I might want to exhibit this behavior.  Today Shaun suggested that I try it as an attached property instead, which might save that hassle.  Indeed it does.  Because of the way attached properties work in Silverlight, it’s possible to use them to attach behavior as well as data be hooking the value changed event.  Here’s the same (basically) logic as an attached property

public class ValidationService
{
    public static readonly DependencyProperty ValidationBehaviorProperty =
        DependencyProperty.RegisterAttached("ValidationBehavior", typeof(bool), typeof(ValidationService),
                                    new PropertyMetadata(OnValidationBehaviorChanged));

    public static bool GetValidationBehavior(DependencyObject d)
    {
        return (bool)d.GetValue(ValidationBehaviorProperty);
    }

    public static void SetValidationBehavior(DependencyObject d, bool value)
    {
        d.SetValue(ValidationBehaviorProperty, value);
    }

    private static void OnValidationBehaviorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is FrameworkElement)
        {
            FrameworkElement fe = d as FrameworkElement;

            if ((bool)e.OldValue)
            {

            }
            if ((bool)e.NewValue)
            {
                fe.BindingValidationError += new EventHandler<ValidationErrorEventArgs>(fe_BindingValidationError);
            }
        }
    }

    static void fe_BindingValidationError(object sender, ValidationErrorEventArgs e)
    {
        FrameworkElement fe = e.OriginalSource as FrameworkElement;
        DependencyObject parent = fe.Parent;
        Border b = null;

        if (parent is Grid)
        {
            b = new Border() { BorderBrush = new SolidColorBrush(Colors.Red), BorderThickness = new Thickness(0) };

            Grid g = parent as Grid;
            g.Children.Add(b);
            int column = (int)fe.GetValue(Grid.ColumnProperty);
            b.SetValue(Grid.ColumnProperty, column);
            int row = (int)fe.GetValue(Grid.RowProperty);
            b.SetValue(Grid.RowProperty, row);
            g.Children.Remove((UIElement)fe);
            b.Margin = fe.Margin;
            fe.Margin = new Thickness(0);
            b.Child = (UIElement)fe;
        }
        else if (parent is Border)
        {
            b = parent as Border;
        }

        if (e.Action == ValidationErrorEventAction.Added)
        {
            if (b != null)
            {
                b.BorderThickness = new Thickness(1);
            }
            ToolTipService.SetToolTip(fe, new TextBlock() { Text = e.Error.Exception.Message });
        }
        if (e.Action == ValidationErrorEventAction.Removed)
        {
            if (b != null)
            {
                b.BorderThickness = new Thickness(0);
            }
            ToolTipService.SetToolTip(fe, null);
        }
    }
}

Note that when registering the attached property, we register a value changed handler (in this case OnValidationBehaviorChanged).  This will get called the first time the property is set, which gives us an opportunity to mess with the element that the property is attached to.  If the value of the property is being set to true, we hook up the BindingValidationError handler.

In the validation error handler, we have to find out if the element is currently surrounded by a Border, and add one if it isn’t.  Note: in this example it will only work if the element is originally the child of a Grid.  This could easily be modified to support the other Panel types. 

Once the parent is a border, then the old logic from the previous example can be reused to set the border and tooltip on or off as appropriate. 

Notice that we don’t mark the BindingValidationError event as Handled so that it will bubble.  That allows us to write additional forms specific error handling higher up in the visual hierarchy.  At the form level we might want to invalidate the submit button if validation failed, or something similar, while letting the logic in the attached property handle the UI effects.

In the XAML, this new attached property can be used to attached the desired visual effect to any FrameworkElement like so

<TextBox Width="Auto" x:Name="txtNewHours"  Text="{Binding Hours, Mode=TwoWay, Converter={StaticResource hoursConverter}, 
    NotifyOnValidationError=true, ValidatesOnExceptions=true}" 
    my:ValidationService.ValidationBehavior="true"
    Grid.Row="1" Grid.Column="1" Margin="5,5,5,5"/>
Friday, 20 February 2009 15:32:07 (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, 19 February 2009

Stuart posted a great solution he came up with for writing dynamic orderby queries in LINQ when you don’t know the “column” name that you want to sort by ahead of time.

Thursday, 19 February 2009 13:38:59 (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 

I’m going to be teaching two new one-day courses on setting up a Continuous Integration process, one using freely available tools, and one using Microsoft Team Foundation Server.  For more details and to register, see our registration page.

Both classes will be held at the Westside campus of OIT

Course Description:

This one day course will provide a hands on look at setting up a Continuous Integration process using freely available tools from beginning to end. Students will learn the theory and practice behind establishing a Continuous Integration process, including setting up a build script, running unit tests, setting up an automated build/test server, and capturing reporting information for the whole process.

Course Technology

This course uses Microsoft Windows XP, the Microsoft .NET 3.5 Framework, NAnt, NUnit, and CruiseControl.NET.

At the end of the course you will be able to:

  • Create a build script using NAnt or MSBuild
  • Create and run unit tests using NUnit
  • Set up and run an automated build using CruiseControl.NET
  • Capture reporting data from the automated CI process

Course Outline
    Continuous Integration in Theory
    • Why CI is important
    • How CI fits into the Software Development process
    Creating a build script
    • What goes in a build script?
    • How does NAnt work?
    • How does MSBuild work?
    • Creating build scripts for NAnt or MSBuild
    • Running an automated build
    Adding unit tests to your build
    • Writing NUnit tests
    • Running tests as part of a build
    • Capturing test results
    Continuous Integration with CruiseControl.NET
    • Installing and configuring CC.NET
    • Adding projects to a build server
    • Reporting with CC.NET
    • Running multiple builds on the same server
        Dependencies between builds

Prerequisites

This class is intended for experienced .NET 2.0 software developers.

Thursday, 19 February 2009 12:37:26 (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, 18 February 2009

I was having a bit of trouble getting validation to work during data binding in SL, but that seems to be resolved now.  I’ve got a little time tracking app, and want to be able to log new time entries…

CropperCapture[8]

I want the user to be able to enter hours only in 1/4 hour increments.  The way that gets handled in Silverlight is different from WPF.  To make it work in Silverlight the data binding source has the throw an exception if the new value is unacceptable.  In this case, the source is a “LogEntry” class that has a property “Hours” that implements INotifyPropertyChanged to support full two-way data binding.

public class LogEntry : INotifyPropertyChanged
{

    private decimal hours;
    public decimal Hours 
    {
        get
        {
            return hours;
        }
        set
        {
            if ((value % .25M) != 0)
            {
                throw new Exception("please enter time in quarter-hour increments");
            }
            if (hours != value)
            {
                hours = value;

                NotifyPropertyChanged("Hours");
            }
        }
    }

    private void NotifyPropertyChanged(string p)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(p));
        }
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion
}

In the property setting for the Hours property, if the value isn’t evenly divisible by .25 an Exception gets thrown.  In the XAML, the binding is set up to notify (as a binding error) when an exception gets thrown

 

<TextBox Width="Auto" x:Name="txtNewHours"  Text="{Binding Hours, 
    Mode=TwoWay, 
    Converter={StaticResource hoursConverter}, 
    NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>

The grid that holds all the controls handles the BindingValidationError event, which is where all the fun stuff happens…

private void newEntryGrid_BindingValidationError(object sender, ValidationErrorEventArgs e)
{
    if (e.Action == ValidationErrorEventAction.Added)
    {
        //not valid
    }
    if (e.Action == ValidationErrorEventAction.Removed)
    {
        //now it's valid
    }
}

OK, so now I know when the value isn’t valid, but what to do about it.  In WPF, the easiest thing to do would be to use a “decorator” to add a border around the UI element that failed validation, but in Silverlight we don’t get decorators.  Instead, I wrapped each item that needed to support validation in a red border with a thickness of 0 in XAML.

<Border BorderBrush="Red" BorderThickness="0">
    <TextBox x:Name="txtNewHours" Text="{Binding ...}"/>
</Border>

That’s a little extra work that I’d rather not do, but there it is.  It would be easy to wrap up this behavior in a custom control, but this was much quicker.

In the validation handler then, all we have to do is get the original source of the binding error and use the VisualTreeHelper to get it’s parent.  If that parent happens to be a border, set the border’s thickness to 1 to make it visible.  I’m also setting the tooltip for that offending control to be the message of the validation error.  If the ValidationErrorEventAction == Removed, then get rid of the tooltip and set the border’s thickness back to 0.

private void newEntryGrid_BindingValidationError(object sender, ValidationErrorEventArgs e)
{
    if (e.Action == ValidationErrorEventAction.Added)
    {
        DependencyObject ui = e.OriginalSource as DependencyObject 
        DependencyObject parent = VisualTreeHelper.GetParent(ui);
        if (parent is Border)
        {
            ((Border)parent).BorderThickness = new Thickness(1);
        }
        ToolTipService.SetToolTip(ui, new TextBlock() { Text = e.Error.Exception.Message });
    }
    if (e.Action == ValidationErrorEventAction.Removed)
    {
        DependencyObject ui = e.OriginalSource as DependencyObject 
        DependencyObject parent = VisualTreeHelper.GetParent(ui);
        if (parent is Border)
        {
            ((Border)parent).BorderThickness = new Thickness(0);
        }
        ToolTipService.SetToolTip(ui, null);
    }
}

CropperCapture[9]

That same code should work for any control that I want to do validation on, as long as I remember to add the borders in XAML. 

Wednesday, 18 February 2009 14:10:45 (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, 13 February 2009

In the wake of our Silverlight presentations this week, Shaun (CTO of SoftSource, and my boss) is going to be blogging on his demos, starting with Silverlight/JavaScript interactivity.  His demos were pretty cool, so I’m looking forward to reading his commentary.  I might just follow suit with a few examples too…

Friday, 13 February 2009 12:16:28 (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 

Check out http://events.sftsrc.com/ for more new classes…

  • LINQ
    • 2 days of LINQ to Objects, LINQ to XML, LINQ to SQL, LINQ to Entities and more
  • ASP.NET
    • 5 days of ASP.NET including some AJAX and a hint of Silverlight
  • WPF
    • 3 days of WPF goodness
  • Silverlight
    • 2 days for those with WPF experience or
    • 3 days for web developers
  • C#  and the .NET Framework
    • 5 days of C# 3.0 and the 3.5 framework, including LINQ, extension methods and the rest of the new language features
Friday, 13 February 2009 10:17:36 (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, 06 February 2009

Google is great at providing 20/20 hindsight. 

The little problem I was having with insert triggers is (unsurprisingly) not uncommon.  I googled a bit after a suggestion in a comment (thanks El Guapo) and found a great explanation by Mike Taulty on how to deal with just such a concurrency problem.  He’s specifically dealing with a timestamp column, but the issue is essentially the same. 

Good to know…

Friday, 06 February 2009 09:39:15 (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, 05 February 2009

I’ll be there, soaking up the Silverlight-y goodness. 

Thursday, 05 February 2009 14:56:38 (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  |