开发者

How can I Import my ViewModels without breaking MVVM?

开发者 https://www.devze.com 2023-04-11 19:00 出处:网络
[Export] public sealed class MainViewModel : NotificationObj开发者_高级运维ect { [Import] public ISomeService MyService { get; private set; }
[Export]
public sealed class MainViewModel : NotificationObj开发者_高级运维ect
{
    [Import]
    public ISomeService MyService { get; private set; }

    ...
}

In order to INJECT this class as the DataContext to my View, I have to mark it as Export so MEF creates an instance of it in the Catalog. The problem is that the main window needs to create other windows and pass in orders, I'm not sure how to go about that without breaking the MVVM approach.

I figure that an ICommand will trigger something on my MainViewModel to generate a new ViewModel, but then after that happens I can't really force a new Window (view) to open up from the ViewModel. Plus, I can't even really create a new ViewModel from my MainViewModel because then MEF won't really work, right?

[Export]
public sealed class MainViewModel : NotificationObject
{
    [Import]
    public ISomeService MyService { get; private set; }

    private ObservableCollection<IOrderViewModel> Orders { get; set; }

    public void OpenOrder(int id)
    {
        //Pseudo-code to ensure that duplicate orders are not opened)

        //Else create/open the new order
        var order = new OrderViewModel(id);

        OpenOrders.Add(order);
    }
}

2 problems here:

  1. Since I "newed" the OrderViewModel services are not autoloaded via MEF.
  2. How does this code on my ViewModel layer (appropriate layer) create the necessary view as a NEW WINDOW (child of the main window), and then link this new OrderViewModel as the DataContext?


The way to avoid 'new-ing' the OrderViewModel is to use a factory:

[Export]
public class OrderViewModelFactory
{
    [Import]
    public ISomeDependency ImportedDependency { get; set; }

    public OrderViewModel Create(int id)
    {
        return new OrderViewModel(id, this.ImportedDependency);
    }
}

Then import the factory into your MainViewModel as a dependency and MEF will take care of filling everything in as required.

To get around the problem of instantiating windows, we have created a DialogService that does something like:

[Export]
public class DialogService
{
    public bool? ShowDialog(string regionName, object data = null)
    {
        var window = new Window();
        var presenter = new ContentControl();
        presenter.SetProperty(RegionManager.RegionName, regionName);
        window.Content = presenter;
        if (data != null) window.DataContext = data;
        return window.ShowDialog();
    }
}


One technique I use is what I call the Navigation service. Note this is different from WPF's built in navigation framework. Your viewmodel could have an instance injected directly or you can use the EventAggregator pattern to fire a request to navigate that then gets handled by the navigation service. Having the navigation service injected directly means that it can be injected with other objects like ViewModelFactories. Regardless how you do it, at some point you're going to have to have an object that knows how to create the viewmodel properly resolved by your container.

0

精彩评论

暂无评论...
验证码 换一张
取 消