Why to avoid the codebehind in WPF MVVM pattern?

why the empty codebehind is regarded as a a well-designed MVVM

Having a code-behind file which consists solely of a call to InitializeComponent() in its constructor means you have achieved purity – you have absolutely zero logic in your codebehind. You have not polluted your view with any code that rightfully belongs in the viewmodel or model. This means a couple of things:

  • the viewmodel (and model) is easier to test in isolation
  • you have achieved a good level of loose coupling, which has excellent benefits from a maintenance and extensibility perspective

The benefits really become noticeable when you have to change your UI, i.e. you switch from using a ListView to a DataGrid, or you change from using the standard Microsoft controls to using some other vendor’s.

As mentioned though, it is sometimes impossible to avoid a little code in the code-behind file. What you should ensure is that the code you do have is purely UI related. As an example, if you have ComboA and ComboB, and ComboB is set in response to the selection in ComboA, then setting the SelectedIndex of ComboB from the view is fine, but setting the Items or the SelectedItem of ComboB is not – those properties are both data related and should be specified via binding to the viewmodel. The SelectedIndex property is directly visual related and somewhat independent of the actual data (and it is irrelevant to the viewmodel).

If you do access the viewmodel from code-behind in the view, you should try and do it via an interface. This means your viewmodel is injected or given to the view as an interface. (Note that the binding subsystem doesn’t know or care about the interface, it will continue to bind in its normal way. What this achieves is better code, with less tight coupling). The way I code it, the viewmodel has no idea that a view exists, and the view only knows about the viewmodel as an interface.

One thing to remember though is that MVVM is a pattern, and a pattern is simply a recipe or prescription for achieving a certain result in a certain situation. It shouldn’t be treated as a religion, where non-believers or non-conformers are going to go to some purgatory (although adherence to the pattern is good if you want to avoid the purgatory of maintenance hell and code smell).

If you want an excellent example of how this particular pattern helps, try writing a few reasonably complicated screens in ASP.Net, and then write the same in WPF or Silverlight, and note the difference.


Edit:

let me answer some of your questions, I hope it helps….

the viewmodel’s (model of view) role , in my view, has UI logic and state of a view

The viewmodel should never have any UI logic or “view state” in it. For the purposes of this explanation, I would define view state as scroll position, selected row index, selected index, window size, etc. None of those belong in the viewmodel; things like SelectedIndex are specific to the way the data is shown in the UI (if you change the sort order of a DataGrid then the SelectedIndex can change, even though the SelectedItem is still the same). In this particular case, the SelectedItem can be bound to the viewmodel, but the SelectedIndex shouldn’t.
If you need to keep track of UI session type info them then you should come up with something generic (for example, I have persisted view state before by saving important stuff into a KeyValuePair list) which is then “saved” with a call to the viewmodel (via the interface I mentioned previously). The view has no idea how the data is being saved, and the viewmodel has no idea the data is coming from a view (it has simply exposed a call through its interface).

and the view’s role is displaying some contents and synchronizing the viewmodel(having databinding code)

Yes, the view’s responsibility is simply to visually display data presented by the viewmodel. The viewmodel gets the data from the model (the model is responsible for making database calls or WCF webservice calls, this will usually be done via a “service”, but that is a whole other discussion). The viewmodel can then shape or manipulate the data, i.e. it may get a list of all customers, but only expose a filtered version of that list (maybe the current customers) in a public property which the view can then bind to.
If the data is to be manipulated into something visual (a common example is an enum value being translated into a color), then the viewmodel still only has the enum value(s), and the view still binds to that value, but the view also uses a converter to translate the pure data to a visual representation. By using the converter the viewmodel has still avoided doing anything UI related, and the view has avoided any real logic.

Leave a Comment