Programming notes and tools...

MVVM and Code Behind

Wed, 20 Mar 2019 MVVMWPFC#

If you search the web you will find countless articles deploring the use of WPF code behind and stating categorically that any use whatsoever is anti-MVVM. I disagree with this sweeping assertion and whilst it is true that most uses of code behind tend to be anti-MVVM (and hence liable to cause you pain in the future) there are some use cases where code behind is exactly the right tool for the job.

First lets remind ourselves what MVVM is. MVVM is a design pattern that fits very nicely with Microsoft's WPF UI framework. It stands for Model-View-ViewModel and provides a three layer approach for separating your business logic from your view logic. The idea is that each layer knows about the one directly below it but not any layers below that or any layers above it. The layers are as follows:

So how does all this relate to code behind?

WPF (which is often used for the View component of MVVM) provides you with two code files per view, a XAML file and a C# code behind file. The XAML file uses XAML, an XML based language, to define the UI layout. XAML is a pretty rich language allowing you to define graphs of UI components and how they bind (talk to) the underlying View Model. What is hard to do in XAML is define the type of logic which should really be in the View Model or even the Model, as such a good rule of thumb to ensure separation of concerns is to try to define all your view logic in XAML.

The problem comes when you take the "avoid code behind" rule of thumb as a hard and fast rule. Sometimes you will encounter a view requirement that is impossible to encode in XAML itself. WPF gives us various tools to solve these sorts of problems including converters and attached behaviors, it also gives us code behind. All of these tools involve writing code in C#, not XAML, to augment the XAML code for your view. Converters and attached behaviors allow you to reuse your code across views but can be more complex to implement (especially if you want to make them generic enough to be able to reuse them).

Code behind is often the simplest solution and if your problem is specific to a single view then I would argue code behind is the correct solution (why add complexity when you don't need to). The way I think about this is that the XAML, code behind, converters and attached behaviors are all part of your view, they are all tools you can use for building views and none of them should include any logic that belongs in a layer other than the view.

A good example of where code behind is very useful is when using a DataGrid with a dynamic set of columns. In this instance the view model should be providing the data for the DataGrid including information on the columns. The code behind of the view can then listen to changes in columns and update the columns in the DataGrid itself. Whilst this could also be achieved with an attached behavior, if this is specific to a single view there is no need for the extra effort an attached behavior requires.

I have also seen a lot of code where people claim "this is MVVM, look, no code behind!" but have stuffed their converters and even more so their attached behaviors, with business logic which should not be anywhere near the view. Just because you don't have code behind doesn't mean its MVVM but it can still be MVVM with code behind. Remember, MVVM is a design pattern, it doesn't specify any language or framework, just a way of separating concerns.

So in summary, the rule of thumb, "avoid code behind" is a useful guideline but if you truly understand what MVVM is about and why it is useful you will know when the guideline can be ignored.