Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

True MVVM and third party controls

In a True MVVM model we do not expect any code behind in xaml.cs also we do not expect viewModel to have refernece of view. However all third party controls do not provide good support for True MVVM.

In my case I am using Infragistics xamDatagrid control and I want to export its data to excel. The only way I can export data to excel of data grid is by using following code:

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

However, XamDataGridExcelExporter takes input as this.xamDataGrid. xamDataGrid is part of View not viewModel. So how can we handle such kind of cases where we need instance of view in viewModel.

like image 996
Pradeep Avatar asked Jun 29 '11 04:06

Pradeep


2 Answers

It is a common misconception that MVVM forbids code-behind. The truth is that code-behind is not reusable and it is inseparable from the view, so it cannot be unit tested without automation. But it does have its uses.

There is nothing inherently bad about code-behind. In fact, it's not much different than all the other code your write in support of your view like converters, custom controls, etc. None of this code can be tested by your view-model unit tests. The only difference with code-behind is that it is less reusable. But it's still part of your view and views are not bad.

In general, the absence of code-behind is a good indicator of a clean separation between the view and the view-model. However the presence of some code-behind in an otherwise clean design usually merely indicates something that is hard to do with the standard controls and data binding and commands.

In your case, exporting the XamDataGrid is definitely view-specific. It has to do precisely with the third-party library you have chosen for the view. So it makes perfect sense that it should not be part of the view-model.

If you are are still dead set against any code-behind, you can use behaviors, such as ACB or Blend Behaviors to write functionality that you would otherwise put into the code-behind. Just realize that even behaviors are still part of the view, only more reusable that code-behind.

like image 185
Rick Sladkey Avatar answered Sep 30 '22 22:09

Rick Sladkey


You can write a wrapper around xamDataGrid that has a dependencyproperty called filename. The viewmodel can then bind to this property. When the xamDataGrid detects a change on the filename property it can then execute the code you suggested. Afterwards reset the filename property for further notification.

This solution keeps out the code from you code behind and makes the xamDataGrid responsible for exporting its data.

-------edit---------

A second solution can make use of the MVVM light messenger class. In stead of declaring a dependency property, make your wrapper listen to a message. When the viewmodel sends the message (which could for example have the filename as parameter) the wrapper can then execute the code.

eg

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

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

    }
}

Then in your viewmodel you can do:

 Messenger.Default.Send(@"C:\Excel\ExportFile.xls","ExportExcel");

There are many solutions to your problem, all of which you do not have to start writing logic in your view.

http://www.lucbos.net/2011/06/using-codebehind-in-mvvm.html

like image 44
Luc Bos Avatar answered Sep 30 '22 22:09

Luc Bos