28 August 2012

Death by a thousand updates

At work we have a whole bunch of tools to aid us during our development struggles day in and day out. Since the release of VS 2012 last week I took the opportunity to update our tool suite: VS 2012, ReSharper 7, updated SVN, moved to a beta quality Gallio/MbUnit v3 and the list goes on.

To tell the truth this didn't go well. We were already struggling with Visual Studio and ReSharper bugs, but the Gallio Plugin for ReSharper is really the one that caused us the most grief. Unfortunately the folks at JetBrains do not support Gallio out of the box and the Gallio development work seems to have slown down quite a bit. ReSharper 7 is not supported by the current edition of Gallio. Oh well, what do we do now?

We can't provide support for it at work as we're always struggling with our own schedule. So we've decided to dare and look at our unit tests and make an effort to check portability to NUnit. Now there's a reason we decided to use MbUnit in the first place: Contracts, Assert.Multiple, Threading support and lots of other icing on the cake.

To give you a number: We have over 22000 unit tests for our main product. So right in the middle of our sprint we decided a switch to VS 2012 is necessary - so many improvements - and ReSharper 7 has some nice additions too.

It took us a whole week to switch our entire test base from MbUnit to NUnit 2.6. It was actually a great experience and we have found several false-positive tests, which reported green even though they were broken. It turned out that MbUnit probably has some bugs too :)

Now I hope that JetBrains fixes some of the pesky ReSharper 7 bugs, that are really slowing us down.

10 July 2012

WPF DataGrid: Enable inline adding of records for view models with non-default constructors/interfaces

If you're using MVVM with interfaces you've certainly seen that the WPF DataGrid doesn't display an empty row at the end and does not allow the user to add new rows to the grid. An example:

interface IPersonViewModel
   string FirstName { get; set; }
   string LastName { get; set; }

interface IPersonListViewModel
    IList<IPersonViewModel> Persons { get; }

If you bind IPersonsListViewModel.Persons to a DataGrid you will not see an empty row at the end allowing the user to add new rows. The reason is that the DataGrid does not know how to instantiate IPersonViewModel for the new row (or more correctly the ListCollectionView.)

We've been struggling with this for the last couple of days as we're porting our WinForms app to WPF and are throwing away our custom data binding engine we've used for WinForms for the last three years.

The issue is as I said above that ListCollectionView does not know how to instantiate new rows and thus returns false from its CanAddNew property. We've solved it by creating a custom ListCollectionView which uses a factory function (a delegate) to create new rows. This is the class:

   public class TypedListCollectionView<T> : ListCollectionView, IEditableCollectionView
       private Func<T> factory;

       public TypedListCollectionView(IList collection, Func<T> factory)
           : base(collection)
           this.factory = factory;

       bool IEditableCollectionView.CanAddNew
               return this.CanAddNewItem;

       object IEditableCollectionView.AddNew()
           T obj = this.factory();
           return this.AddNewItem(obj);

The class overrides two interface methods from ListCollectionView. CanAddNew checks if CanAddNewItem is supported by the base class in order to not break the internal logic of ListCollectionView related to editing and new items. The other overload AddNew uses the factory method provided to the constructor to create the new row and passes this to the AddNewItem method of ListCollectionView. This keeps the ListCollectionView internal logic working and enables the DataGrid to add new rows.

06 October 2011

Thank you.

Dear Steve,

there's so much inspiration you've given. There's so many beautiful things you've created. So many lives touched by the ideas you supported. My thoughts are with you, your family and Apple.

Love what you do. Don't settle. Keep looking until you find what you love.

Thank you for sharing.