Hi Mike. Excellent question.
You're absolutely right that this approach departs from the MVVM pattern. I tried to be clear about that. It is most definitely an example of a different MV* pattern, a flavor of Model-View-Presenter known as "Supervising Controller".
Had I insisted on maintaining the MVVM pattern, come hell-or-high-water, I would have implemented an event such as you've described. I would have felt it necessary to reduce the code behind too so I'd either write an attached property to (a) look for the event and, if found, (b) bind the event. I could do that with a re-usable helper instead (that's really what an attached property is).
Notice that my purist instincts would drive me beyond adding an event handler. I'd worry that the VM might not expose that event. I don't want my View to be statically dependent upon the VM any more than I want the VM to be statically dependent upon the View. So I'd invent some way to cope.
Maybe I'd give the VM an interface (instead of the View interface that was used here). Then I could see if the VM implemented that interface and only attach the handler if it did. Keeping the coupling loose would mean the the View wouldn't care if the VM did or did not expose such an event and the VM can raise the event whether or not a view is subscribing.
But then where would I store the interface if the View and VM are divided in separate assemblies (it happens)? Maybe I'd have to use reflection (that's what the Data Binding machinery does). Definitely going to need a helper for that. More work ahead.
The greatest advantage to the pure MVVM approach you suggest is that VMs do not have View references. The same VM can drive any number of views simultaneously. That might be important if this were a Windows Metro app in which it is likely that multiple Views (Landscape, Portrait, Snapped) are bound to the same VM. This particular Happy Hour implementation does NOT support multiple bound Views; I'd have to come up with some way to hold multiple views and visit each of them when a DrinkOrder is added. Doable but not so much fun.
The last point seems to argue in favor of your proposal. And yet ... I didn't do it that way. Why?
Well you made the case for me. You had to write some less-than-obvious code in both the VM and the View to use events ... two events at that (DC Changed and DrinkOrderAdded)!
[aside: DataContextChanged is in Silverlight 5 but not in Silverlight 4. The sample supports both.]
Eventing is inherently more indirect and therefore always at least a little harder to follow than imperative code of the kind used in this sample. Extra complexity and obscurity has to return value. It often does. Does it pay off here?
Different developers will feel differently from case to case. In this example I wanted to show that Cocktail (Caliburn) supports a hybrid approach. This screen is mostly MVVM with a touch of Supervising Controller.
It comes down to what YOU want to do. I personally don't mind a little Supervising Controller ... and it's good to see how Caliburn supports it. If you do mind, go right ahead and introduce the event mechanism.
Gold star for bringing this topic up. A discussion of options and how-we-choose benefits everyone.
p.s.: As the sample evolves, the need to set the focus becomes irrelevant because the TextBox disappears. All your hard work to preserve MVVM through eventing will be discarded. Oh well ... that's programming for you :)
Edited by WardBell - 09-Apr-2012 at 4:41pm