Bit of a long title… But commanding in photon has some sweet features which help create really simple view models. There’s no need for ICommand, DelegateCommands or constantly calling RequerySuggested. The view simply uses the view model methods. You TDD out your view model and stick a view on later. This is a big part of our goal because we don’t have all the UX requirements at the start of the sprint. I’ll resist the temptation of talking about how we work with UX, I’ll save that for another post…
This example is slightly contrived. It’s as real as I could come up with in as few lines of code as possible… Let’s imagine you need to deliver a screen which lets you set user contact preferences:
- The user should be able to capture if the caller would like to be contacted in the future
- If the caller would like to be contacted the user must record at least one contact method
So first story, what does our view model look like?
First thing to notice is our view model inherits ModelBase. Photon provides a base class which implements INotifyPropertyChanged (and the validation interfaces, more on this later). Next we’re setting the property using the SetProperty method. This will fire the notify changed and also hooks into the commanding infrastructure (we’ll see this working shortly).
Next, let’s add to it to support recording the contact methods:
Ok, so we added a new view model for holding the contact method. I’ve also written some methods which let people add and remove preferences… Now we need to put a view on this. One thing I’ve been using recently is designer data, it makes life so much easier in Blend because you can see what you’re doing.
Important thing with IsDesignTimeCreatable must be true, otherwise it doesn’t work!
Tip here is to use ReSharper to bring in the namespace reference. Type <ContactPreferenceViewModel in the XAML, ReSharper will pop up asking if you want to import the namespace, hit alt enter. Done.
Now you can data bind up to the view model…
Anyway, I digress…
We need a button to add contact methods, and we need to hook the button up to our AddContactMethod method… This is done by adding an event trigger with an InvokeMethod action and setting the MethodName property accordingly:
Now we need somewhere to show the Contact Methods, so let’s use a list box and stick a TextBox (bound to the ContactMethod string) and a Remove button.
Now this is where Scoping comes in… The data context in our list box is the ContactMethodViewModel. This doesn’t have the remove method, it’s on the ContactPreferenceViewModel… We can use the Invoke.Target attached property to tell the method binding action where to look for the method. Now you can drop on the MethodInvoke action as before, only this time you set a parameter (the first parameter of the method is the contact method to remove). The list box ends up looking like this:
So got a working view… Two things to do… You shouldn’t be able to add contact methods if the customer is not contactable. Also, if they are contactable you have to capture at least one contact method. So let’s add these method to the view model.
Now photon will automatically re-evaluate the can methods for you… It does this when properties change, no need for any other code:
So in summary, you get some interaction actions you can drop on in blend which call methods (we may add a short hand syntax for non-blenders). There’s a base view model which sorts out all the boiler plate Property Changed logic. This also hooks in with the Photon CommandManager so you don’t need to re-evaluate Can Execute methods. There’s also Invoke.Target so you can call methods which are not associated with the current data context.
There’s more documentation of Method Invocation on the Photon CodePlex site, along with all the Source Code… I hope to post some more stuff up about how we use Photon along with how we work with blend, UX and more…