2

My application is going on a break mode after hitting a user button that loads the app setup. I have registered the component in the bootstrapper class.

How can I register the constructor of the user controller in bootstrap class so as to avoid the break?

public class Bootstrapper
{
    public IContainer Bootstrap()
    {
        var builder = new ContainerBuilder();

        builder.RegisterType<LoginView>().AsSelf();
        builder.RegisterType<SchoolSectionDataService>().As<ISchoolSectionDataService>();
        builder.RegisterType<AdminView>().AsSelf();

        builder.RegisterType<School>().AsSelf();
        builder.RegisterType<MainSchoolSetupViewModel>().AsSelf();

        return builder.Build();
    }
}

and the user control is:

private MainSchoolSetupViewModel _viewModel;

public School(MainSchoolSetupViewModel schoolSetupViewModel)
{
    InitializeComponent();
    _viewModel = schoolSetupViewModel;
    DataContext = _viewModel;
    Loaded += UserControl_Loaded;
}

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
    _viewModel.Load();
}
Andrei Dragotoniu
  • 6,155
  • 3
  • 18
  • 32
jmutali
  • 33
  • 1
  • 7
  • I don't think you can do this. But you can require the view model with from a static IContainer. There is also the problem of the Injection context but this is more advanced. You could use the AutoWireViewModel trick like in prism if you want to. – Filip Cordas Feb 28 '18 at 15:01
  • Just set the datacontext from XAML. Remove the Constructor parameter. Use the xaml interaction library to invoke the Load method from a command binding with an event trigger. – chancea Feb 28 '18 at 18:23

1 Answers1

3

Unfortunately passing viewmodel into user control's constructor is not possible but there few ways around it. The main thing usually is when building combining DI and XAML and MVVM is that only the view models are registered into the container.

Couple options are mentioned in the comments:

  1. Add a static IContainer property in your Bootstrap. Call it in you user control's constructor to get the VM:

    public School()
    {
        InitializeComponent();
        _viewModel = Bootstrap.Container.Resolve<MainSchoolSetupViewModel>();
        ...
    
    1. Skip DI and instead create the viewmodel instance in XAML:
<UserControl.DataContext>
   <local:SchoolViewModel/>
</UserControl.DataContext>

But it's quite likely that you want to there's other possibilities:

  1. Use ViewModelLocator to help out with DI. This is well documented in this answer: https://stackoverflow.com/a/25524753/66988

The main idea is that you create a new ViewModelLocator class:

class ViewModelLocator
{
    public SchoolViewModel SchoolViewModel
    {
        get { return Bootstrap.Container.Resolve<SchoolViewModel>(); } 
    }
}

And create a static instance of it in App.xaml and use it to create the data context of your user control:

DataContext="{Binding SchoolViewModel, Source={StaticResource ViewModelLocator}}">

For other solutions, one option is to check out source code of some of MVVM Frameworks, like Caliburn.Micro. From Caliburn.Micro you can find ViewModelLocator and ViewLocator which might interest you.

Mikael Koskinen
  • 12,306
  • 5
  • 48
  • 63