Mech0z
Mech0z

Reputation: 3647

Setting datacontext with prism

I am trying to create a module with PRISM and right now I set the DataContext inside the View which means I can only use a Parameterless constructor, but that means I cant use dependency injection (I use Unity) in the constructor which I would like

If it is possible I would like neither the view or the vm to know each other and want to use something like

private void RegisterServices()
{
    var employeeViewModel = new EmployeeViewModel();

    _container.RegisterType<IEmployeeViewModel, EmployeeViewModel>();
    _container.RegisterType<EmployeeView>();

    EmployeeView.Datacontext = employeeViewModel;
}

Which I would register in the EmployeeModule

Is this possible or should I use code behind?

Upvotes: 4

Views: 4037

Answers (2)

FireAlkazar
FireAlkazar

Reputation: 1880

Prism documentation gives you an option

Often, you will find it useful to define a controller or service class to coordinate the instantiation of the view and view model classes. This approach can be used with a dependency injection container, such as MEF or Unity, or when the view explicitly creates its required view model.

For my module I would do the following
Create an interface for service inside module

public interface ICustomModuleUiService
{
    void ShowMainView();
    void ShowExtraView();
}

Production implementation in the same module:

class CustomModuleUiService : ICustomModuleUiService
{
    private readonly IEventAggregator _eventAggregator;

    public CustomModuleUiService(IEventAggregator eventAggregator)
    {
        _eventAggregator = eventAggregator;
    }

    public void ShowMainView()
    {
        var ddsViewModel = new DdsViewModel(_eventAggregator, this);
        DdsForm form = new DdsForm();
        form.DataContext = ddsViewModel;
        form.Show();
    }

    public void ShowExtraView()
    {
        //some code here
    }
}

And finally module code

[ModuleExport("DssModule", typeof(DssModuleImpl))]
public class DssModuleImpl : IModule
{
    private readonly IEventAggregator _eventAggregator;
    private ICustomModuleUiService _uiService;

    [ImportingConstructor]
    public DssModuleImpl(IEventAggregator eventAggregator)
    {
        _eventAggregator = eventAggregator;
        _uiService = new CustomModuleUiService(_eventAggregator);
    }

    public void Initialize()
    {
        _eventAggregator.GetEvent<OpenDdsFormEvent>().Subscribe(param => _uiService.ShowMainView());
    }
}

Using this approach I'll get

  • ViewModel can be unit tested
  • I can dynamically change the reaction on OpenDdsFormEvent by substituting implementation of ICustomModuleUiService

Upvotes: 1

daryal
daryal

Reputation: 14929

You may pass the interface of ViewModel to the View in the constructor. This way, View only knows the interface of ViewModel and ViewModel knows nothing about the View.

Ex.

public class EmployeeView : UserControl
{
    public EmployeeView(IEmployeeViewModel vm)
    {
         this.DataContext = vm; //// better to set the ViewModel in the Loaded method
    }
}

Refer to this blog post for multiple approaches of MVVM instantiation.

Upvotes: 2

Related Questions