0

I've set my View's data context to it's associated ViewModel in the View's code behind. But after reading a question on the MVVM pattern, it's suggested to move this glue code to the View's XAML mark up.

Googling has shown me examples of setting the context below in XAML, by setting a namespace to the VM and setting data context.

Although in my case, the MainViewModel takes a parameter of a CustomerRepository instance, which I'm not sure how to set up in XAML, base on the previous example.

Does anyone know how to move the data context to the View's XAML?

This is how I've currently set the View's code behind in C#:

    public partial class MainView : Window
    {
        private MainViewModel ViewModel { get; set; }

        public MainView()
        {
            InitializeComponent();
            ViewModel = new MainViewModel(CustomerRepository.Instance);
            this.DataContext = ViewModel;

        }

    }
Community
  • 1
  • 1
Brian Var
  • 6,029
  • 25
  • 114
  • 212

1 Answers1

1

You can instantiate your view model in your xaml like this:

<Window x:Class="MyWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="Test" 
            xmlns:viewModel="clr-namespace:ViewModels"> 
        <Window.DataContext>
            <viewModel:ExampleViewModel/>
        </Window.DataContext>
</Window>


You explained that your view model constructor has a parameter for your repository. Do you need this constructor for unit testing purposes?

Usually you can just new up your repository instance in a parameterless constructor of the view model.

public class MainViewModel : ObservableObject, INotifyPropertyChanged
{

    private static CustomerRepository _customerRepository;

    // existing constructor
    public MainViewModel(CustomerRepository customerRepository)
    {
        _customerRepository = customerRepository;
    }

    // new parameterless constructor
    public MainViewModel(CustomerRepository customerRepository)
    {
        if (DesignerProperties.GetIsInDesignMode(this))
        {
            _customerRepository = new CustomerRepository();         
        }
    }
}


Check if is in design mode

There is one more thing you need to think of when creating a view model in xaml: The view models constructor is called at design time when you open the view. So you need to wrap any code in the constructor which does not make any sense at design time into a "only when not in design time" condition. If you do not do this, your view will open with an error in the designer.

This is explained in this response: Check if in design mode

Community
  • 1
  • 1
Martin
  • 5,165
  • 1
  • 37
  • 50
  • okay good suggestions, going to use the method of creating a second parameter-less ctor, that calls the existing. I know how to set up a parameter-less ctor, but how can I define a call from within that to my second ctor? I've seen a suggestion of using the base() but not sure how to implement. My VM is set out like this for reference: https://github.com/BrianJVarley/MongoDB_App/blob/master/MongoDBApp/ViewModels/MainViewModel.cs – Brian Var Nov 14 '15 at 20:42
  • You could call the existing constructor from the new one like this: `public MainViewModel() : this(new CustomerRepository())`. But after thinking about it a second time, i think its best to just create the repository in the new parameterless constructor without calling the existing one. Because then you can check whether you are in design time. See my edited response. – Martin Nov 14 '15 at 21:31
  • cool, have you came across using this https://msdn.microsoft.com/en-us/library/system.windows.data.objectdataprovider.aspx ? As a solution to having an overloaded ctor? I tried using your above suggestion but I can't 'new' my Repo instance as it's static singleton. – Brian Var Nov 14 '15 at 21:33
  • I have not used ObjectDataProvider yet. But i think creating your repository is not the typical usage scenario for the ObjectDataProvider, because it does not make sense to create a class like a repository (which performs database access) at design time. – Martin Nov 14 '15 at 22:24