Friday, July 31, 2009
« Spammed by Google | Main | Adding DataContextChanged in Silverlight... »

The current contender for the pattern to displace IoC as “the trendy pattern” is MVVM: Model-View-ViewModel.

MVVM, often called the ViewModel pattern, has its origins in Silverlight, and to a lesser degree WPF has murky origins (maybe Expression Blend, Smalltalk or from aliens in the 8th dimension). It applies well to Silverlight and WPF, because those environments use XAML to describe the actual user presentation, and there’s a very valid desire to avoid having any code-behind a XAML page. A traditional MVC or MVP model isn’t sufficient to accomplish that goal (at least not efficiently), because it is often necessary to have some “glue code” between the View and the Model, even when using data binding.

The challenge is that some Models aren’t shaped correctly to support the View, so something needs to reshape them. And ideally there’d be some way (WPF commanding or similar) to “data bind” button click events, and other events, to some code other than code-behind. The idea being that when a user selects an item in a ListBox, the code that runs in response isn’t in the code-behind.

The idea behind ViewModel is to create a XAML-friendly object that sits between the View and the Model, so there’s a place for what would have been code-behind to go into a testable object. The ViewModel becomes the container for the code-behind, but it isn’t code-behind. Clearly the ViewModel object is part of the UI layer, so the architecture is something like this.

image

It turns out that there are various ways of thinking about the role of a ViewModel. I think there are two broad approaches worth considering.

ViewModel as Sole Data Source

You can set up the ViewModel to be the sole data source for the View. In this case the ViewModel exposes all the properties and methods necessary to make the View function. This can work well with an anemic Model, where the Model is composed of a bunch of dumb data container objects (think DataTable, DTO and most entity objects).

With an anemic data-centric Model it is common to reshape the Model to fit the needs of the View. And since the Model is anemic, something needs to apply any business, validation and authorization rules and it surely won’t be the Model itself.

Creating this type of ViewModel is non-trivial, because the ViewModel must use containment and delegation (a concept familiar to VB6 developers) to literally wrap, reshape and alter/enhance the behavior of the underlying Model.

image

Every Model property must be reimplemented in the ViewModel, or the View won’t have access to that property. The ViewModel must implement INotifyPropertyChanged, and very possibly the other data binding interfaces (IDataErrorInfo, IEditableObject, etc).

In short, the ViewModel will almost certainly become quite large and complex to overcome the fact that the Model is anemic.

What’s really sad about this approach, is that the end result will almost certainly require more code than if you’d just used code-behind. Arguably the result is more testable, but even that is debatable, since the ViewModel now implements all sorts of data binding goo and you’ll need to test that as well.

ViewModel as Action Repository

Another way to think about a ViewModel is to have it be a repository for actions/commands/verbs. Don’t have it reimplement all the properties from the Model, just have it augment the Model.

This works well if you already have a rich Model, such as one created using CSLA .NET. If the Model is composed of objects that already fully support data binding and have business, validation and authorization rules, it seems silly to reimplement large chunks of that functionality in a ViewModel.

Instead, have the ViewModel expose the Model as a property, alongside any additional methods or properties exposed purely by the ViewModel itself.

image

Again, this presupposes the Model is powerful enough to support direct data binding to the View, which is the case with CSLA .NET business objects, but may not be the case with simpler DTO or entity objects (which probably don’t implement IEditableObject, etc).

The value to this approach is that the ViewModel is much simpler and doesn’t replicate large amounts of code that was already written in the Model. Instead, the ViewModel augments the existing Model functionality by implementing methods to handle View requirements that aren’t handled by the Model.

For example, the Model may be a list of objects that can be bound to a ListBox control in the View. When the user double-clicks an item in the ListBox it might be necessary for the UI to navigate to another form. Clearly that’s not a business layer issue, so the Model knows nothing about navigation between forms. Typically this would be handled by a MouseDoubleClick event handler in code-behind the XAML, but we want no code-behind, so that option is off limits.

Since neither the View nor the Model can handle this double-click scenario, it is clearly in the purview of the ViewModel. Assuming some way of routing the MouseDoubleClick event from the XAML to a method on the ViewModel, the ViewModel can simply implement the method that responds to the user’s action.

This is nice, because the View remains pure XAML, and the Model remains pure business. The presentation layer concept of navigation is handled by an object (the ViewModel) who’s sole job is to deal with such presentation layer issues.

Routing XAML Events to a ViewModel

Regardless of which kind of ViewModel you build, there’s a core assumption that your XAML can somehow invoke arbitrary methods on the ViewModel in response to arbitrary actions by the user (basically in response to arbitrary events from XAML controls). WPF commanding gets you part way there, but it can’t handle arbitrary events from any XAML control, and so it isn’t a complete answer. And Silverlight has no commanding, so there’s no answer there.

When we built CSLA .NET for Silverlight, we created something called InvokeMethod, which is somewhat like WPF commanding, but more flexible. In the upcoming CSLA .NET 3.7.1 release I’m enhancing InvokeMethod to be more flexible, and porting it to WPF as well. My goal is for InvokeMethod to be able to handle common events from a ListBox, Button and other common XAML controls to invoke methods on a target object in response. For the purposes of this blog post, the target object would be a ViewModel.

The ListBox control is interesting to work with, because events like SelectionChanged or MouseDoubleClick occur on the ListBox control itself, not inside the data template. There’s no clear or obvious way for the XAML code to pass the selected item(s) as a parameter to the ViewModel, so what you really need to do is pass a reference to the ListBox control itself so the ViewModel can pull required information from the control in response to the event. In my current code, the solution looks like this:

<ListBox ItemsSource="{Binding Path=Model}"
         ItemTemplate="{StaticResource DataList}"
         csla:InvokeMethod.TriggerEvent="SelectionChanged"
         csla:InvokeMethod.Resource="{StaticResource ListModel}"
         csla:InvokeMethod.MethodName="ShowItem"/>

Notice that the ItemsSource is a property named Model. This is because the overall DataContext is my ViewModel object, and it has a Model property that exposes the actual CSLA .NET business object model. In fact, I have a CslaViewModel<T> base class that exposes that property, along with a set of actions (Save, Cancel, AddNew, Remove, Delete) supported by nearly all CSLA .NET objects.

For the InvokeMethod behaviors, the ListModel resource is the ViewModel object, and it has a method called ShowItem(), which is invoked when the ListBox control raises a SelectionChanged event:

public void ShowItem(object sender, object parameterValue)
{
  var lb = (System.Windows.Controls.ListBox)sender;
  SelectedData = (Data)lb.SelectedItem;
}

The ShowItem() method gets the selected item from the ListBox control and exposes it via a SelectedData property. I have a detail area of my form that is databound to SelectedData, so when the user clicks an item in the ListBox, the details of that item appear in that area of the form. But the ShowItem() method could navigate to a different form, or bring up a dialog, or do whatever is appropriate for the user experience.

The point is that the SelectionChanged, or other event, from a XAML control is used to invoke an arbitrary method on the ViewModel object, thus eliminating the need for code-behind the XAML.

Why this isn’t Ideal

My problem with this implementation is that the View and ViewModel are terribly tightly coupled. The ShowItem() implementation only works if the XAML control is a ListBox. It feels like all I’ve done here is moved code-behind into another file, which is not terribly satisfying.

What I really want is for the XAML to pick out the selected item – something like this pseudocode:

<ListBox ItemsSource="{Binding Path=Model}"
         ItemTemplate="{StaticResource DataList}"
         csla:InvokeMethod.TriggerEvent="SelectionChanged"
         csla:InvokeMethod.Resource="{StaticResource ListModel}"
         csla:InvokeMethod.MethodName="ShowItem"
         csla:InvokeMethod.MethodParameter="{Element.SelectedItem}"/>

Where “Element” refers to the current XAML control, and “SelectedItem” refers to a property on that control.

Then the ShowItem() code could be like this:

public void ShowItem(object parameterValue)
{
  SelectedData = (Data)parameterValue;
}

Which would be much better, since the ViewModel is now unaware of the XAML control that triggered this method, so there’s much looser coupling.

There’s no direct concept for what I’m suggesting built into XAML, so I can’t quite do what I’m showing above. The “{}” syntax is reserved by XAML for data binding. But I’m hopeful that I can make InvokeMethod do something similar by having a special syntax for the MethodParameter value, using characters that aren’t reserved by XAML data binding. Perhaps:

csla:InvokeMethod.MethodParameter=”[[Element.SelectedItem]]”

Or maybe more elegant would be a different property:

csla:InvokeMethod.ElementParameter=”SelectedItem”

Anyway, I think this is an important thing to solve, otherwise the ViewModel is just a more complicated form of code-behind, which seems counter-productive.

Friday, July 31, 2009 10:29:56 AM (Central Standard Time, UTC-06:00)
Great post (as usual) but I had one comment. The {} syntax is not reserved for data binding. They are markup extensions. In WPF, it would be easy to write your own. Unfortunately, we cannot yet write our own in Silverlight (hopefully in 4.0) but its very common to write custom markup extensions.
Friday, July 31, 2009 11:55:07 AM (Central Standard Time, UTC-06:00)
You do not need to pass parameters into the SelectionChanged event with ICommand in Silverlight/WPF as you suggest. You simply create another property on your ViewModel to two-way bind to the SelectedItem.

Then in your SelectionChanged command method, you check the property on the ViewModel for its current value. The good thing about the items controls is they bind their SelectedItem value before they raise the SelectionChanged events.
Adam
Friday, July 31, 2009 11:55:51 AM (Central Standard Time, UTC-06:00)
Thanks for the clarification Shawn, and maybe that'll be an answer in the future. Unfortunately I'm doing this in both WPF and Silverlight, so I think I'm stuck?
Friday, July 31, 2009 12:00:22 PM (Central Standard Time, UTC-06:00)
Thanks Adam - but doesn't that cause a bad smell because every one of my command methods has a side-effect of requiring the concept (and implementation of) a SelectedItem property for that method?

On a form with 30 or 40 combobox controls that could be pretty intense, and it seems like you'd want some cleaner way to make it clear that each method requires a property (or several properties) to be set before the method can be called.
Friday, July 31, 2009 12:32:47 PM (Central Standard Time, UTC-06:00)
How are you data binding the current values into your UI?
Adam
Friday, July 31, 2009 12:38:48 PM (Central Standard Time, UTC-06:00)
I'm in agreement with Adam. I think that binding the SelectedItem directly to a property on your ViewModel is much cleaner. If you have 30 or 40 combobox controls on one form you have bigger problems anyway. :-) If it's really neccessary to have all of those controls on one form, you could at least split the ViewModel up into multiple view model classes. That's one nice thing about XAML - being able to have multiple DataContexts set on different parts of the view. Surely all of those controls aren't one logical group?
Kevin Kuebler
Friday, July 31, 2009 12:56:52 PM (Central Standard Time, UTC-06:00)
I use the ViewModel as the 'Action respository' you describe in a project now. As far as the commanding, I use Rob Eisenberg's Caliburn (www.codeplex.com/caliburn), which allows for a very clean separation. I highly recommend taking a look at his implementation, it's phenomenal.
Josh Huber
Friday, July 31, 2009 1:00:22 PM (Central Standard Time, UTC-06:00)
I have solved the problem of the binding code in the View Model. Please check out Update Controls. With this library, there is absolutely no binding code in the View Model.

Still, you are correct that a View Model tends to be tightly coupled to a View. This view-specific behavior has to go somewhere. Might as well be the View Model.

Finally, I have proposed a pattern I call Navigation Model which solves the problem of the command parameter. Please review this application of the pattern.
Friday, July 31, 2009 1:32:31 PM (Central Standard Time, UTC-06:00)
I think I picked a poor example for the post.

Consider the MouseDoubleClick event instead of SelectionChanged. In this case there's a bigger temporal gap - the selected item might change, then seconds later a doubleclick occurs. But the doubleclick routes to a method in the ViewModel that needs to know the selected item.

Or what if the listbox allows mutliselect? In this case there are numerous (potentially non-contiguous) selected items. When the doubleclick occurs I need to know about all of them.

Yes, I'm sure I could write a ton of code in a ViewModel to track what all items have been selected - but can I do it without coupling myself to a ListBox? And can I solve the temporal issue?

And will this work on a form that has a few hundred controls and perhaps 20 listbox/combobox controls? That's real-world stuff - not that uncommon.

On the other hand, I have no interest at all in making CSLA become a UI framework, so if there are good alternatives that already solve this problem then I don't feel a whole lot of need to get too deep into it.

I'd much rather focus on ensuring full data binding support from the objects and let other people futz with this nasty UI stuff :)
Friday, July 31, 2009 1:34:45 PM (Central Standard Time, UTC-06:00)
Several people have mentioned solutions involving binding a property on my VM to SelectedItem. That seems quite poor - because the VM method invoked by the event then relies on this property. It would be like writing an old vbx control for VB3, where you had to set a bunch of properties before you could trigger the action - the only way to know what was needed was paper docs. Yuck!

Surely we're not regressing that far just for a trendy pattern?
Friday, July 31, 2009 1:38:11 PM (Central Standard Time, UTC-06:00)
Rocky,

Can you say more about MVVM's origins in Silverlight? I'd always thought that it came from the WPF side of XAML because Command Binding makes it work so much better there.

The closest I've ever gotten to finding the origins of the MVVM is in the documentation for the MVVM Toollkit, where we are told that "[t]he origins of this pattern are obscure" but probably came out of the Expression Blend team.

James
Friday, July 31, 2009 2:06:54 PM (Central Standard Time, UTC-06:00)
ListBox is a bad example simply because its multi select isn't data binding friendly. On my ViewModels (which do not power a UI with hundreds of controls, I'd never give someone a single UI element with that much on it), I tend to use property change notifications to trigger my actions.

For instance, you don't need to handle the CheckChanged event, unless there is outside processing that needs done. If it's all inside-the-UI processing - like a check box to power the IsEnabled of another group - then I'd have a property bound to the CheckBox.IsChecked property, then the control being enabled's IsEnabled property bound to that. Or better yet, just element-to-element data binding and skip the view model totally.

The same is true even with certain types of processing you need to do: you have a drop down with a list of choices that powers another list dynamically. To handle that, you bind a property on your ViewModel to the SelectedItem of the drop down. When that property changes, you use a service external to your view model (dependency injection) to get whatever dynamic data you need, then set a different property on your view model to the results.

Also note that I tend to make my view models DependencyObjects in WPF and simply override the OnPropertyChanged event to orchestrate my various property dependencies. Silverlight is a bit more of a pain since neither DependencyObject nor FrameworkElement support OnPropertyChanged, so I tend to just inherit from a base class with INotifyPropertyChanged and a virtual OnPropertyChanged method (and ugly string checking).

Ideally, when dealing with MVVM you need to stop thinking "user clicks X and I need to do Y", it won't let you progress very far with the pattern. Instead think "my UI requires this type of data and shall respond to changes in it" and all of the user interaction with the UI tends to just be setting properties on your view model.

Obviously MVVM is not perfect and there are lots of situations that require you to respond to UI events (multi selection list box) and sometimes break out of the pattern fully (PasswordBox - doesn't support data binding its text).
Adam
Friday, July 31, 2009 2:20:29 PM (Central Standard Time, UTC-06:00)
I agree Adam, there's absolutely no value to MVVM if the VM is just another place to write code-behind code. There must be looser coupling between the V and VM so the VM is more "action oriented".

I know it is a pipe dream, but I always think of two roles: designer and UI developer. The designer creates the XAML and doesn't know C#. The UI developer knows C# and not XAML, and they have access to the Model (created by a third person) as a black box.

The VM then, must expose functionality required by the designer, but in a way that doesn't dictate what the XAML/controls are used by the designer. Similarly, the designer can't know what is in the VM - just that the VM exposes actions X, Y and Z and properties A, B and C.

But I do think ListBox is a good example, because it is a common scenario, and if MVVM can't handle a common scenario then the pattern has a problem with reality, and is thus not a good pattern.

I think the pattern, in broad strokes, is a good one. I just think the issues (like ListBox, or initial loading of a form that requires parameter data) need to be addressed in a simple and concise manner.
Friday, July 31, 2009 2:35:05 PM (Central Standard Time, UTC-06:00)
I don't personally blame the pattern... I blame the inconsistencies in the controls. XAML introduces this new powerful data binding, but it wasn't done perfectly and has some holes.

I'm still a little unsure what your problem w/ the double-click is. Is it only that you want an ICommand respond to the double-click but don't want to have the command rely on something in the view model?

First off, you should have two-way data bound the selected item on your input control if it's something you need to ever get the value from later (aside from input for the double click).

Second, then it seems like the only problem there is the fact that Silverlight doens't support ICommand, since what you've implemented is already implemented in full WPF for things like buttons and anything that supports a Command/CommandParameter property.

In Silverlight, what you've done is what a lot of others have also done: create a behavior for a given event and provide a way to bind an ICommand to it. It's not perfect since most Silverlight events aren't RoutedEvents so you can't have one generic behavior like you're wanting, but with a tiny bit of copy/paste you can handle a good majority of events. In an app I'm writing, I just wrote two attached behaviors for MouseEnter/MouseLeave that support invoking an ICommand, and passing a parameter to it (and you can data bind a value into the parameter).

(In a random UIElement control, you can add this)
behaviors:MouseEnterCommandBehavior.Command="{Binding MouseEnterCommand}"
behaviors:MouseEnterCommandBehavior.ComandParameter="{Binding ElementName=SomeListBox, Path=SelectedItem}"

It's not perfect, but with Silverlight you've got some ugly changes from WPF that create a lot of headaches and you just have to deal with them.
Adam
Friday, July 31, 2009 2:52:20 PM (Central Standard Time, UTC-06:00)
Adam,

I'm actually starting with SL and worrying about WPF as a secondary concern.

I want commands to route to resources in any case, because I want absolutely ZERO lines of code behind the XAML - so I need my VM object to be created as the page is created, much like a data provider control. WPF commands can't target arbitrary objects, which is a serious limitation imo.

Subsequent to writing this blog post I've done a lot more work, and now have InvokeMethod working as I want, so it can invoke arbitrary methods on arbitrary objects in response to arbitrary events from any UI control.

And thanks to a friend pointing out just how far the new SL3 data binding enhancements go (and comments by you and others here), I'm data binding the SelectedItem or SelectedItems (for multi-select) property of the ListBox to my MethodParameter property.

In short, I didn't need to invent any new parsing or binding syntax - the existing stuff works just fine.

So this works now:

<ListBox ItemsSource="{Binding Path=Model}"
ItemTemplate="{StaticResource DataList}"
csla:InvokeMethod.TriggerEvent="SelectionChanged"
csla:InvokeMethod.Target="{Binding}"
csla:InvokeMethod.MethodName="ShowItem"
csla:InvokeMethod.MethodParameter="{Binding SelectedItem, RelativeSource={RelativeSource Self}}"
csla:InvokeMethod.ManualEnableControl="True" />

in both SL and WPF, and the ShowItem() method accepts one parameter which is the selected item.

Decent decoupling, because the View knows little about the VM, and the VM knows little about the View. The two only agree that there's a ShowItem() action that requires the item-to-show as a MethodParameter.

Switch the ListBox to mutliselect and bind to SelectedItems and it works too - with no more coupling.
Friday, July 31, 2009 3:30:42 PM (Central Standard Time, UTC-06:00)
Yep, you definitely can't bind a command to any arbitrary object. I don't know if that's necessarily a bad thing, but it is limiting. Apparently the WPF people assumed that either your "code behind" would handle the method (as in the event of CommandBindings and RoutedCommands) or an object that implements ICommand. Most people I know have built things like "ActionCommand" which accept an Action or Action&lt;object&gt; so they don't need to build lots of command classes. Then it's pretty easy to use DI to supply the implementation for a given action into your view model and create an ActionCommand to invoke it.

I don't personally mind the limitation, but I can understand how one might.
Adam
Saturday, August 01, 2009 4:19:57 AM (Central Standard Time, UTC-06:00)
"MVVM, often called the ViewModel pattern, has its origins in Silverlight, and to a lesser degree WPF." I don't think this is true Rocky - the Blend team (built with WPF) and its architect John Gossman were really the forerunners with this pattern (and John himself is reluctant to take credit for it - citing a number of similar patterns in smalltalk).

Also, there is a way to bind a number of 'arbitrary gestures' to Commands in WPF: http://www.thejoyofcode.com/Invoking_a_Command_on_a_Double_Click_or_other_Mouse_Gesture.asp

As with most things - the tiny silverlight runtime is playing catchup here.

One thing not to get too caught up in is the desire to have *absolutely no* code-behind. As you're finding, this can quickly run into the diminishing returns bracket. Instead, think of the view as the combination of Xaml and code-behind. As with most things we prefer the ratio to be hugely in favour of the declarative but sometimes, you just need some code-behind. In this case an event handler calling a method (or executing a command) on your ViewModel is fine - it keeps the VM clean, pure and canonical.

Finally, I want to show my support for the TwoWay binding to a SelectedItem property - it just works and works really well - this is now a proven and tested approach. Comparisons to VB3 and the like come across a little angry and unmeasured.

It's actually pretty beautiful when you think of the ViewModel as a canonical representation of the 'presentation state'. We just allow the presentation state to be modified and both parties (views and viewmodel) can be observed.
Saturday, August 01, 2009 8:38:46 AM (Central Standard Time, UTC-06:00)
It is quite possible that I don't have the history of the pattern correct. I'll freely apologize to anyone I misused, offended or otherwise harmed by saying that this pattern started in Silverlight.

On to important stuff:

I think the ZERO code behind is critically important, because I'm also spending a lot of time with Oslo. And in that world the View is pure XAML. As soon as you contaminate anything with a 3GL your life gets much, much more complex. So if there is to be code-behind, it has to be in the form of a XAML workflow or something, not C#.

Finally, if you don't like my comparsion to VB3, I'll gladly compare the concept to FORTRAN if you'd like. The idea of a consumer calling a sequence of methods, in order, to achieve a desired result was proven to be a terrible idea over 15 years ago. It was bad in FORTRAN, it was bad in Pascal and it was bad in VB3.

I'll buy arguments that it is pragmatic, that it works, or that it is the best we can do with this technology. But I won't buy arguments that it is actually a good idea, because it isn't.

However, I'll take your last paragraph as a different approach. Then I'll agree. If the ViewModel is not an action repository, but is just a state repository, then I'm with you. But that means the action repository needs to be in some other location - and even then it feels to me like we're playing semantics without addressing the real problem.
Saturday, August 01, 2009 8:48:28 AM (Central Standard Time, UTC-06:00)
Sunday, August 02, 2009 12:39:02 AM (Central Standard Time, UTC-06:00)
"Finally, if you don't like my comparsion to VB3, I'll gladly compare the concept to FORTRAN if you'd like. The idea of a consumer calling a sequence of methods, in order, to achieve a desired result was proven to be a terrible idea over 15 years ago. It was bad in FORTRAN, it was bad in Pascal and it was bad in VB3."

It's not so much that I don't like it - more that I don't understand it. I don't see how the view setting a property on the VM (via a binding) to report a change in state is like what you describe above.

WRT to the Oslo stuff then you're clearly out there on the bleeding edge and you'll be blazing a new trail. But at the moment, that isn't the problem MVVM is trying to solve for most of us. You can get there through attached properties/behaviours but that is just moving the code-behind elsewhere - but at least in a *reusable* way that I think should work OK with Oslo.

MVVM isn't perfect (what pattern is) but it provides greater separation, less test-friction and greater support for designer/developer workflow than MVP or MVC. There are lots of challenges that need solving (Validation is one area I'm struggling with lately and animation is another). Nonetheless its tremendously empowering. I just finished a 3 week POC at the Microsoft Technology Centre in Reading and we finished our goals, stretch goals and even made up some new goals and the resulting code was maintainable and application looked great because MVVM allowed us to work with designers in a relatively seamless manner.

PS - can you fix the unclosed link in the previous comment - it's driving the page mad.
Sunday, August 02, 2009 5:22:25 PM (Central Standard Time, UTC-06:00)
I completely agree with Josh here, the end goal of building ViewModels is not about zero code, it's about building UIs that are easier to maintain, whether the person maintaining is a developer or a designer. And in most shops, the designer doesn't really exist (at least yet anyway), so it's a developer doing the work, and making life easy for them and their team. Also for folks that are concerned about testability, ViewModel provides a nice way of building UIs in a testable fashion. (Of course some will debate just how nice it is, INPC anyone?)

Having code in the code-behind itself is not right off the bat an anti-pattern. It's when that code creates unnecessary coupling, that the maintability bar starts going up. It depends on the type of code. For example, if I want my VM to trigger the start of an animation in my View, then I see no problem in having a line of code in the View which starts that animation.

Now yes, you can use (what I consider hacks) to create triggers or attached behaviors in the view that respond to changes in the VM and do that work for you, but such "logic" in the view is very brittle and easy to break, it's just loose markup. The compiler doesn't help you at all. Not to mention the fact that XAML although humanly consumable is not very readable. Try looking for the needle in a haystack in an XAML file of any complexity and you know what I am talking about.

Don't get me wrong, I absolutely think one should minimize the code in the code-behind, as if there is code, it is a possible indication that the ViewModel / Databinding is not being properly leverage. However, I wouldn't remove code at the sake of reducing the overall maintainability of the code.


Sunday, August 02, 2009 9:39:30 PM (Central Standard Time, UTC-06:00)
Maybe this is why I'm finding MVVM a little underwhelming - maybe I'm expecting too much, and I should really be looking at other solutions.

But I don't know that we're that far apart in concept.

I have no problem with "script code" being in code-behind. You know, the stuff that makes UI candy work. The stuff a designer with coding capability would write. I know it isn't "script", but it is the code that would be script in the web, or in a game or whatever.

But if the code-behind interacts with the Model, then that's where I think the problems start. So when I say "no code behind", I really mean no code-behind that calls methods on the model, or does anything important, like navigate the user to another form or something.

In short, any code necessary for the app to actually work (as opposed to look good) shouldn't be in code-behind - it should be somewhere else.

That somewhere else could be custom controls, a ViewModel, a Controller, etc.

And even more important - any code necessary for the app to properly execute any business functionality (business, validation, authorization rules, algorithmic processing, etc) should be in the Model. I should feel comfortable that if I slap a Windows Forms or XML service interface on top of my Model that I'll get exactly the correct business behaviors.
Sunday, August 02, 2009 11:00:52 PM (Central Standard Time, UTC-06:00)
The code in the code-behind should not be invoking the ViewModel rather it should be handling UI-specific concerns. I also agree with the statement about generally keeping anything important out of the View, certainly any business logic. So if this is the sense of zero-code then we are on the same page.

The place where I see exception is when there is logic that either needs to get invoked by the View or some other service, such as starting an animation or displaying some inline dialog. Having it in the code-behind means the ViewModel is still in control, having it in the XAML however shifts the control away from the VM and thus puts it in a very brittle place where it is difficult to debug and to test. In the code, I can't test that the animation works, but at least I will get an exception if OnSave fires an animation and it the animation was removed, also I can put a break point to at least see that it is getting called.

Regards
Glenn




Sunday, August 02, 2009 11:04:04 PM (Central Standard Time, UTC-06:00)
As far as the ViewModel having selected properties and parameterless commands, what exactly do you see as the anti-pattern in this? It certainly doesn't stop the designer as they simply need to set up the correct bindings. As far as the ViewModel having 50 different properties for a UI that has 50 different selected items, so what?

I would argue that having the 50 properties actually makes it much more discoverable from a code-perspective, and also reduces the brittleness of the UI, as if I have that many places where I am using element binding, then the likelihood that it will break is EXTREMELY high.

My $.02
Glenn
Saturday, August 08, 2009 10:36:18 AM (Central Standard Time, UTC-06:00)
wow. mvvm, although relative easy to grasp in terms of the concept, sounds daunting to implement except for very simple views.

For instance, in asp.net if I had a listview and needed to set some property of a control for each row, I would simple use the ItemDataBound event.

Also, in my webforms I have :

-cascade binding on list boxes
-checks for user permissions
-inserting an empty item in the first row of a combobox
-opening file and save dialogs

etc...

I am not sure I could write a complete business application using the concept of a codeless view and actually deliver the application on time and within scope. I could see myself struggling for days on specific problems like those above.

Is there anything wrong with evolving to the MVVM concept? at least while you are learning it? What I mean is adopt the viewmodel approach, but still use code-behind for some things until such a time you learn how to implement the logic outside of the codebehind.

Steve
Friday, August 14, 2009 7:32:48 AM (Central Standard Time, UTC-06:00)
You can actually do all that you are asking without a single line of code by using the new assembly: System.Windows.Interactivity. There is a version for both Silverlight and WPF. I have created a custom TriggerAction that looks like the following in XAML:

<ListBox ItemsSource="{Binding Path=Model}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<trg:ExecuteCommandTrigger TargetCommand="ActionCommand" UserState="lbSample" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>

In your ViewModel you have a standard ICommand that has an OnActionCommand that takes a custom class that I call EventEntity. This class wraps all of the information about the event that fired. It looks like this:

/// <summary>
/// This class provides the ability to query the parameter and userstate objects when invoking the ExecuteCommandTrigger.
/// </summary>
public class EventEntity
{
public string UserState { get; set; }
public object Parameter { get; set; }
public FrameworkElement AssociatedObject { get; set; }
};

The OnActionCommand looks like this:

private void OnActionCommand(EventEntity e)
{
if (e.UserState == null) return;

switch (e.UserState.ToLower())
{
case "lbSample_SelectionChanged":
if (e.Parameter is System.Windows.Controls.SelectionChangedEventArgs)
{
// Do something...
}
break;
}
}

This pattern can be used for any event that fires in XAML. It is extremely powerful and the Blend 3 guys have been using this since Mix '09. Hope this provides some insight. I have my own MVVM framework that uses this approach quite extensively. I have access to the event args, custom user state, and the sender object as well.
Matt Duffield
Friday, August 14, 2009 10:54:31 AM (Central Standard Time, UTC-06:00)
The only problem I see with triggers is that they don't inherit from FrameworkElement, and so they aren't valid binding targets in Silverlight. This means you can't use binding expressions to set the properties of the trigger, which seriously reduces their utility.
Friday, August 14, 2009 2:50:31 PM (Central Standard Time, UTC-06:00)
Yes you are right there but you can use a trick to support binding on non Framework elements using AttachedProperties. Just a thought.
Matt Duffield
Comments are closed.