TOP

No Code-Behind for MVVM

One of the annoying things when you start working with Model-View-ViewModel in Windows Presentation Foundation (WPF) is the fact that you can’t just delete the code-behind file for your .xaml files.

After discussing the problem with Peter Lillevold, he came up with a solution to our problem. Let’s first discuss the problem and then present the solution.

Initialize Component

When you look at a recently created XAML file, you’ll notice there is a call to the InitializeComponent in the constructor. This is an operation that is not available in the derived type (Window, Page, UserControl) nor is it directly visible in your project. Right-click on the method call and Go To Definition (F-12) opens an generated file you normally don’t see.

The operation is responsible for loading (initializing) the XAML which is embedded as a resource in your application binaries.

Example of a code-behind class:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }
}

Unfortunately the XAML views require this call to InitializeComponent to function properly, if you go ahead and delete the code-behind file you’ll end up with an blank window/user control when they are loaded.

View Base Types

The solution is to provide a view-base for all your top-UI containers, such as Window, Page and UserControl. These view-base types can additionally be used to construct convention-based initialization of View Models in an MVVM-pattern implementation. This is beyond the scope of this post, might be visited in a future post.

Here is an example on how to do this for a Window view:

public partial class WindowView : Window
{
    public WindowView()
    {
        var initializeComponentMethod = GetType().GetMethod("InitializeComponent",
            BindingFlags.Public | BindingFlags.Instance);
        if (initializeComponentMethod != null)
        {
            initializeComponentMethod.Invoke(this, new object[0]);
        }
    }
}

First we tries to get an reference to the current instance of the object, which will return the inherited type (for example “ExampleView” type as included in my sample source code). Then we validate if the method actually exists and if it does, we invoke the InitializeComponent method.

Next step is to change the XAML markup so you no longer use the framework type for Window, Page or UserControl, but instead your own custom base view types. At this point you can delete the code-behind of your XAML files, just make sure you don’t delete any existing logic that you might have in your code-behind.

Side note: Having logic in code-behind is not a violation of good practices, even when you’re working with the MVVM (Presentation) pattern.

Open your XAML and add a statement that imports the CLR namespace where your view types are, e.g.

xmlns:NoCodeBehind="clr-namespace:NoCodeBehind"

Then change the root-XML-element in your XAML markup file to e.g.

<NoCodeBehind:WindowView 

Note that the x:Class element on the root element dictates the name of your view, meaning your XAML file can be named something other than the generated type of the view.

Example Source Code

For a concrete example of this implementation in WPF and how you can avoid the code-behind file altogether is included below. The two examples are ExampleView.xaml and ExampleControl.xaml which both works without code-behind files.

Please use the example with caution and there are no guaranties that the workaround doesn’t change some behavior in your running application. Any feedback is welcome, please leave comments!

Download the NoCodeBehind example in C#.

Leave a Reply

Your email is never published nor shared.

You may use these HTML tags and attributes:<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>