woensdag 29 juni 2011

Using the codebehind in MVVM

Today I saw a topic on stackoverflow where a user asked a question on how to solve a certain piece of code that needed a UI element in MVVM.  Just an hour later a bunch of answers popped up telling him that it’s no problem putting this code in the code behind.  I disagree!

The piece of code the user was talking about was this:

xamDataGridExcelExporter.xamDataGridExcelExporter xamDataGridExcelExporter1 =      
new xamDataGridExcelExporter.xamDataGridExcelExporter();  
xamDataGridExcelExporter1.Export(this.xamDataGrid1,  
    @"C:\Excel\ExportFile.xls");

An argument to putting this kind of code in the code behind was that this is UI code.  UI code?  It’s not that because the Export method of XamDataGridExcelExporter accepts a UI element that it suddenly turned into UI code. 

When I see this piece of code I can think of a number of solutions that can isolate this piece of code from the UI.  We can for example inherit from XamDataGrid and make it responsible for its own export to excel.  Should the XamDataGrid be sealed then we can make a wrapper that does exactly the same thing.

So that just moves the problem you might think.  We still need a mechanism so the ViewModel can trigger this action.  This is where the Messenger class of MVVM light can be very handy.  On the initialization of the object we can register ourselves to a message and initiate our export action.   

Here is a quick example:

    public class XamDataGridWrapper : XamDataGrid
    {
        public XamDataGridWrapper()
            : base()
        {
            Messenger.Default.Register<string>(this, "ExportExcel", ExportFile);
        }

        private void ExportFile(string file)
        {
            xamDataGridExcelExporter.xamDataGridExcelExporter xamDataGridExcelExporter1 =      
            new xamDataGridExcelExporter.xamDataGridExcelExporter();  
            xamDataGridExcelExporter1.Export(this,  
                @"C:\Excel\ExportFile.xls");

        }
    }

The reason I would not encourage anyone for putting code in the codebehind unless it’s absolutely necessary is because of the broken window effect. A developer will see the code in the codebehind and quickly think, why not add a little more to make my life easy?  Granted that doing everything the MVVM way can be a brain teaser sometimes, but fragmenting your code between the ViewModel and the codebehind will give you more trouble than it’s worth afterwards.

To finish I’ll give a few examples in what (in my opinion are) cases you should use/not use the codebehind:
Not use codebehind:

  • Lack of dependency property
  • Invoking methods on a UI element
  • Laziness ;)
  •  
Use codebehind:
  • Interactive animations / storyboards (eg: animation based on mousespeed)
  • Accessing navigationservice
Till next time

Geen opmerkingen:

Een reactie plaatsen