Friday, April 22, 2011

Getting .Net Property Names without Magic Strings

This was something that had been perking my interest every so often ever since I started truly adopting Agile development practices and re-factoring code with abandon. This meant that properties and methods could be added, removed, and renamed at any point within the life of a project. There are cases where in debug messages, log entries, reflection lookups, or Argument-related exceptions I want to extract a property name. This resulted in a magic string appearing in the code.

A classic example of needing property names is with WPF binding and PropertyChanged events. Your viewmodels may be listening for property changes on bound domain objects in order to perform actions or update calculated values. Take for example:

The problem here is that if properties within InterestRate (Delta, Rate, and EffectiveDate) are renamed, the above code will stop working as expected. Now effective unit tests should help guard against behaviour changes but it would be nice if we could avoid having a hard-coded string for the property name.

Enter the PropertyName method: I had come across a solution a while ago on Clinton's Blog around using a static method to extract property names. It worked well enough but it was still a bit clumsy. What I ended up with was:

This works well enough but I didn't really like having to explicitly declare the Type (In the above example: InterestRate x) in the parameter expression. Lately I got thinking why this functionality couldn't be adapted into an extension method...

Now the calling code looks like:

This is a compliment to the GeneralToolbox static method in that the extension method will only work against an instance of a class where the static method can work against the type. (In situations where an instance isn't present.)

- Edit: Code & unit tests are now available here.

Monday, April 11, 2011

Around 6+ hours I'd love to get back.

WPF is a beautiful thing most days, but every so often it rears up and slaps you in the face when all you think you have left is a fairly trivial bit of UI functionality left. Then you are burning HOURS making sure you haven't done something completely stupid in your bindings, and Dr. Googling for anyone else who's run into the same problem. The burn isn't that it's a particularly complex thing to do, it's that there end up being so many variations of things to try, most of which won't work for one reason or another, and many other suggestions simply never worked or were even tried. This burns hours upon hours. Even if I say to myself "This isn't that important, set it aside and come back to it later" it's still smouldering in my mind and within a couple minutes I'm back trying something else that comes to mind, and burning more time on it.

In this case all I had left were two little unrelated UI interactivity features that I wanted to polish off before continuing with the next set of requirements.

#1. I present details in a list that is sorted by date. In editing an item within the list I can edit the date. The logical behaviour is that the list should be re-sorted.

#2. Presented in the list rather than using separate views for viewing and editing the details I wanted to swap out a data template (or user control) inside the list item content. (Click a button to expand for edit/review, and another to save/restore to summary mode.)

WPF has Collection View Source objects that sounded like they should have fit my needs for item #1. (instead of binding directly to observable collections)  WPF also has DataTemplateSelectors which looked like they should service my needs for item #2. All set! Not quite....

CollectionViewSource allows you to sort sure enough, but editing the collection items doesn't cause the view source to refresh the sorting/grouping. I spent HOURS of digging and experimenting with different options to tackle this including extending ObservableCollection to provide the sorting, (see here) refreshing via Move operations, to trying to hook into the CollectionViewSource.View.Refresh() with limited success. Finally I hit paydirt with someone that got fed up with exactly the same problem. (see here)

After finally tackling #1 I had renewed energy to tackle #2. (which ironically I had shelved in order to tackle issue #1) I had arm-wrestled with the data template selectors earlier and quickly found while they were good at picking a template, they did not listen for changes to anything they were bound to in order to make that selection so they were only good for a one-off choice. This time the inspiration for the solution came from a little gem of an idea I glanced upon from Stack Overflow (see here), specifically "You could even make your data template a ContentControl, and use a trigger to change the ContentTemplate." I had used DataTriggers before and knew I could swap out individual controls between view and edit variations but I was looking to swap out an entire template in one go. Using a data template containing a content control, and the data trigger to swap out the content template was bloody BRILLIANT!

Finally these WPF UI thorns in my side have been removed and I can resume work without these damn things flaring up to burn up even MORE time. I find it very strange that implementing such functionality was such a chore within WPF, but in case Randall Doser ever comes across this blog... #2, definitely #2.