0
votes

I am building a large scale WPF app - kind of a desktop that hosts multiple modules such as multiple Terminal windows over RS232/Ethernet, Register analyzer, automation tools, etc. I am working with MVVM architecture where my view (XAML) instantiate the corespondent viewmodel in its resource section. and the view model is set in the data-context of the view. in this method the view created first.

however, I red about another method called VM first, meaning view model is instantiated before the view, and I understood the theory that stands behind it. What I didn't understand is when and who instantiate the view and how it happens without coupling to the view.

I'll be more than happy to hear your thoughts, and please if someone can supply code samples it would be great..

Thanks in advance.

4
@Sheridan don't think it's a dupe of that question. Existing question is a very specific use-case of VM first (switching views). This is more general.Tim Rogers
It may not be an exact duplicate, but the answer from that question will answer his question. You are welcome to vote to reopen this question if you disagree.Sheridan
use caliburn micro caliburnmicro.codeplex.com/…Nahum
Seconded for Caliburn Micro...BenjaminPaul

4 Answers

1
votes

I'm using MVVM heavily in my projects and can share my view on this. In my projects the view never instantiates any VM. Usually I have some kind of manager which takes care that the corresponding VM is created.

This I'm assign to the datacontext of some top-level UI control (Window for instance). The view is always defined by a style where the target type is set to the type of the view model. The startup code just creates a Window and the main viewmodel. The VM is assigned and the rest is done by the WPF (.net) runtime so to say.

So I have a large style file, where all the styles for each viewmodel defines the corresponding view (usually a usercontrol).

This is the way I'm doing things, there are for sure others too.

hth

0
votes

To decouple the view from the view-model, something else needs to instantiate the view model and manage its lifetime and sharing. That job might fall to an IoC container, or simple, manual dependency injection. It's entirely up to you.

E.g. from Paul Stovell's article:

public CalculatorView(CalculatorViewModel viewModel)
{
    InitializeComponent();
    DataContext = viewModel;
}

It all depends on you're trying to achieve by decoupling. One reason might be so that you can have multiple views over the same view-model - in that case, whatever creates the views needs to also create the view-model.

Another may be to swap the view-model of an existing view out with another view-model without destroying the view. In that case, maybe you already have two existing view-models and you assign them to the view's DataContext as required.

view.DataContext = viewModels[0];
view.DataContext = viewModels[1];
0
votes

when your application grows you usually face these decisions. Usually you have "always" both elements together the View and the ViewModel it's not about what comes first it's more like what will you use to instantiate the two elements (view and viewmodel). For larger projects, when I had the need, I used a class called ViewModelResolver. It obviously has an interface IViewModelResolverso it can be injected nicely. It can either return a ViewModel based on convention based on type or a string representation and uses reflection to instantiated it. You can also pass in a ViewModel (or type) and get the matching view with the passed in view model as DataContext (view ViewModel marriage) or you can define other custom scenarios that you need for instantiating either view or ViewModel.

hope that helps

So the main point is to have an intermediate class that acts like some sort of factory service that takes car of bringing views and view models together and instantiate them. This gives you more freedom and a good place to separate out those decisions from the ViewModel directly.

0
votes

In my WPF / MVVM applications I use ViewModels with two constructors - one for design time (no paramaters - mock version of required components are set directly) and another for runtime (required components are injected as parameters via IoC). This allows for (mock) data to be displayed inside the Visual Studio designer for UI testing purposes.

So the simple case looks like ...

public class MainViewModel : ViewModelBase
{
    private IDataFactory _DataFactory;

    public MainViewModel()
    {
        _DataFactory = new DesignTimeMockDataFactory();
        LoadData();
    }

    [PreferredConstructor]
    public MainViewModel(IDataFactory dataFactory)
    { _DataFactory = dataFactory; }

    public void LoadData()
    { DataItems.AddRange(_DataFactory.GetDataItems()); }

    public ExtendedObservableCollection<DataItem> DataItems { get; private set; }
}

The design time usage can be set directly in the XAML ...

<Window x:Class="MainView"
        d:DataContext="{d:DesignInstance Type=MainViewModel, IsDesignTimeCreatable=True}"
...

The run-time ViewModel is set in the code behind of the View ...

public MainView()
{
    InitializeComponent();

    var viewModel = SimpleIoc.Default.GetInstance<MainViewModel>();
    DataContext = viewModel;
    Loaded += (s, e) => viewModel.LoadData();
}

The View's Loaded event is set to call the LoadData() method of the ViewModel to trigger data loading, once the View is displayed. If LoadData() is slow, it can be changed into an async method to prevent the UI from blocking.

For those of you complaining that this is a too tightly coupled construct, my view is that is exactly how they are supposed to be. Although the View and ViewModel are separate entities, each View knows exactly what type of ViewModel it requires, and that's unlikely to change over the project development life-cycle. Using a Locator type class to hide the ViewModel constructor calls is an unnecessary level of abstraction in my opinion.