# Simplifying MVVM

## Content

The Model-View-View-Model (**MVVM**) pattern is gaining in popularity as developers realize the benefits it gives their applications, making them easier to maintain and test and, particularly in the case of WPF and Silverlight applications, allowing a much clearer division of labor between the designer of the UI and the creator of the code that makes it work. However, without effective tools to aid program development based on **MVVM** patterns, programmers can actually find themselves working harder because of the need to implement an extra layer (the View Model) and ensure that data is properly synchronized between that and the Model. This extra burden isn’t onerous when you have a relatively small application with just a few simple collections (and best practice with MVVM is to use **ObservableCollection** as the datasource), but the bigger it becomes and the more collections it spawns, the worse it becomes. **DataSource for Entity Framework** can ease the burden.

[C1DataSource](/componentone/api/win/online-datasource/dotnet-framework-api/C1.Win.Data.Entity.4.8/C1.Win.Data.Entities.C1DataSource.html) lets you use live views as your view model. Just create live views over your model collections and use them as your view model. Live views are synchronized automatically with their sources (model), so you don’t need *any* synchronization code - it’s all automatic. And live views are much easier to create than to write your own view model classes using **ObservableCollection** and filling those collections manually in code. You have all the power of LINQ at your disposal to reshape model data into live views. So, not only does synchronization code disappear, but the code creating view models is dramatically simplified.

To demonstrate how easy it is to follow the **MVVM** pattern using live views, let’s create a form combining all features from two previous examples: the **Category-Products** master-detail from [Working with DataSources in Code](/componentone/docs/win/online-datasource/DesignTimeFeatures/WorkingwithDataSourcesinCode2) and the reshaping/filtering/ordering of data from [Live Views](/componentone/docs/win/online-datasource/DesignTimeFeatures/LiveViews). It will be a **Category-Products** view, showing non-discontinued products whose unit price is at least **30**, ordered by unit price, and displaying a customized set of product fields in a master-detail form where the user can select a category to show the products of that category. We'll follow the **MVVM** pattern. The form (view), called **CategoryProductsView**, only hosts GUI controls (a combo box and a grid) and does not have any code except what is used to set the data source to the view model, like this:

DOC-DETAILS-TAG-OPEN
DOC-SUMMARY-TAG-OPEN
To write code in Visual Basic
DOC-SUMMARY-TAG-CLOSE

```vbnet
PublicClassCategoryProductsView
     PrivateviewModel AsCategoryProductsViewModel= NewCategoryProductsViewModel()
     PublicSubNew()
         InitializeComponent()
         comboBox1.DisplayMember = "CategoryName"
         comboBox1.ValueMember = "CategoryID"
         comboBox1.DataSource = viewModel.Categories
         dataGridView1.DataSource = viewModel.Products
     EndSub
 EndClass
```

DOC-DETAILS-TAG-CLOSE
DOC-DETAILS-TAG-OPEN
DOC-SUMMARY-TAG-OPEN
To write code in C#
DOC-SUMMARY-TAG-CLOSE

```csharp
publicpartialclassCategoryProductsView: Form
 {
     CategoryProductsViewModelviewModel = newCategoryProductsViewModel();
     publicCategoryProductsView()
     {
         InitializeComponent();
         comboBox1.DisplayMember = "CategoryName";
         comboBox1.ValueMember = "CategoryID";
         comboBox1.DataSource = viewModel.Categories;
         dataGridView1.DataSource = viewModel.Products;
     }
 }
```

DOC-DETAILS-TAG-CLOSE

All logic is in the view model class, separate from the GUI. More exactly, there are three classes: **CategoryViewModel**, **ProductViewModel**, and **CategoryProductsViewModel**. The first two are simple classes defining properties with no additional code:

DOC-DETAILS-TAG-OPEN
DOC-SUMMARY-TAG-OPEN
To write code in Visual Basic
DOC-SUMMARY-TAG-CLOSE

```vbnet
PublicClassCategoryViewModel
     PublicOverridablePropertyCategoryID AsInteger
     PublicOverridablePropertyCategoryName AsString
 EndClass

 Public ClassProductViewModel
     PublicOverridablePropertyProductID AsInteger
     PublicOverridablePropertyProductName AsString
     PublicOverridablePropertyCategoryID AsInteger?
     PublicOverridablePropertyCategoryName AsString
     PublicOverridablePropertySupplierID AsInteger?
     PublicOverridablePropertySupplierName AsString
     PublicOverridablePropertyUnitPrice AsDecimal?
     PublicOverridablePropertyQuantityPerUnit AsString
     PublicOverridablePropertyUnitsInStock AsShort?
     PublicOverridablePropertyUnitsOnOrder AsShort?
 EndClass
```

DOC-DETAILS-TAG-CLOSE
DOC-DETAILS-TAG-OPEN
DOC-SUMMARY-TAG-OPEN
To write code in C#
DOC-SUMMARY-TAG-CLOSE

```csharp
public classCategoryViewModel
{
    public virtual int CategoryID { get; set; }
    public virtual string CategoryName { get; set; }
}
public classProductViewModel
{
    public virtual int ProductID { get; set; }
    public virtual string ProductName { get; set; }
    public virtual int? CategoryID { get; set; }
    public virtual string CategoryName { get; set; }
    public virtual int? SupplierID { get; set; }
    public virtual string SupplierName { get; set; }
    public virtual decimal? UnitPrice { get; set; }
    public virtual string QuantityPerUnit { get; set; }
    public virtual short? UnitsInStock { get; set; }
    public virtual short? UnitsOnOrder { get; set; }
}
```

DOC-DETAILS-TAG-CLOSE

And here is the code for the **CategoryProductsViewModel** class:

DOC-DETAILS-TAG-OPEN
DOC-SUMMARY-TAG-OPEN
To write code in Visual Basic
DOC-SUMMARY-TAG-CLOSE

```vbnet
PublicClassCategoryProductsViewModel
     Private_scope AsEntityClientScope
     Private_categories AsBindingSource
     PublicPropertyCategories AsBindingSource
         Get
             Return_categories
         EndGet
         PrivateSet(value AsBindingSource)
             _categories = value
         EndSet
     EndProperty
     Private_products AsBindingSource
     PublicPropertyProducts AsBindingSource
         Get
             Return_products
         EndGet
         PrivateSet(value AsBindingSource)
             _products = value
         EndSet
     EndProperty
     PublicSubNew()
         _scope = Program.ClientCache.CreateScope()
         DimCategoriesView AsObject=
             Fromc In_scope.GetItems(OfCategory)()
             SelectNewCategoryViewModelWith
             {
                 .CategoryID = c.CategoryID,
                 .CategoryName = c.CategoryName
             }
         Categories = NewBindingSource(CategoriesView, Nothing)
         DimProductsView AsObject=
             Fromp In_scope.GetItems(OfProduct)().AsFilteredBound(Function(p) p.CategoryID.Value).BindFilterKey(Categories, "Current.CategoryID").Include("Supplier")
             SelectNewProductViewModelWith
             {
                 .ProductID = p.ProductID,
                 .ProductName = p.ProductName,
                 .CategoryID = p.CategoryID,
                 .CategoryName = p.Category.CategoryName,
                 .SupplierID = p.SupplierID,
                 .SupplierName = p.Supplier.CompanyName,
                 .UnitPrice = p.UnitPrice,
                 .QuantityPerUnit = p.QuantityPerUnit,
                 .UnitsInStock = p.UnitsInStock,
                 .UnitsOnOrder = p.UnitsOnOrder
           }
          Products = NewBindingSource(ProductsView, Nothing)
     EndSub
 EndClass
```

DOC-DETAILS-TAG-CLOSE
DOC-DETAILS-TAG-OPEN
DOC-SUMMARY-TAG-OPEN
To write code in C#
DOC-SUMMARY-TAG-CLOSE

```csharp
public classCategoryProductsViewModel
{
    private C1.Data.Entities.EntityClientScope _scope;
    publicBindingSource Categories { get; private set; }
    public BindingSource Products { get; private set; }
    public CategoryProductsViewModel()
    {
        _scope = Program.ClientCache.CreateScope();
        Categories = new BindingSource(
            from c in _scope.GetItems<Category>()
            select new CategoryViewModel()
            {
                CategoryID = c.CategoryID,
                CategoryName = c.CategoryName
            }, null);
        Products = new BindingSource(
            from p in _scope.GetItems<Product>().AsFilteredBound(p =>
            p.CategoryID).BindFilterKey(Categories,
                 "Current.CategoryID").Include("Supplier")
            select new ProductViewModel()
            {
                ProductID = p.ProductID,
                ProductName = p.ProductName,
                CategoryID = p.CategoryID,
                CategoryName = p.Category.CategoryName,
                SupplierID = p.SupplierID,
                SupplierName = p.Supplier.CompanyName,
                UnitPrice = p.UnitPrice,
                QuantityPerUnit = p.QuantityPerUnit,
                UnitsInStock = p.UnitsInStock,
                UnitsOnOrder = p.UnitsOnOrder
            }, null);
        }
}
```

DOC-DETAILS-TAG-CLOSE

Basically, it contains just two LiveLinq statements, nothing more. The statements (creating live views, see [Live Views](/componentone/docs/win/online-datasource/DesignTimeFeatures/LiveViews)) are wrapped in **BindingSource** constructors to add currency, current item, support to the **Categories** and **Products** collections exposed by the view model class. Note that using **BindingSource** is only necessary in WinForms, because the WinForms platform is not as well suited for MVVM as WPF or Silverlight. Note also that because we use **BindingSource**, you need to add the following statement to the code file (in WinForms only):

```csharp
using System.Windows.Forms;
```

Similar to what we saw in [Working with DataSources in Code](/componentone/docs/win/online-datasource/DesignTimeFeatures/WorkingwithDataSourcesinCode2), using **AsFilteredBound**() gives us server-side filtering. We also connected the filter key, which is the **Product.CategoryID** property, to the **CategoryID** selected by the user using a combo box event. Here we can’t do this because we must keep our code independent of the GUI. So we use a [BindFilterKey](/componentone/api/win/online-datasource/dotnet-framework-api/C1.Data.Entity.4.8/C1.Data.FilteredView-1.BindFilterKey.html) method to bind the filter key to the **Category.CategoryID** property of the item currently selected in the **Categories** collection. This is one reason why we need to support currency in the **Categories** collection and why we wrapped it in a **BindingSource** to get currency support in WinForms.

The **Include** ("Supplier") operator is not strictly necessary; it is used here for performance optimization. Without it, **Entity Framework** will fetch **Supplier** objects lazily, one-by-one, every time the user accesses an element of the **Products** collection whose **Supplier** was not yet fetched. This can cause delays, and it’s generally much less efficient to fetch data in single rows rather than in batches, so we opted out of lazy loading here using **Include**("Supplier"), which tells the **Entity Framework** to fetch supplier information in the same query with products.