Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dependency Injection WPF MVVM Navigation .NET Core

I need some help to understand how to instantiate ViewModels without having all of them as parameters in the MainViewModel Class constructor.

Could any of you help me to get my head around and get rid of so many parameters in the constructor. I've read about FactoryPatterns but I don't understand how to implement it or maybe that is not the solution?. Anyway here's the code.

Thank you. Pls help me this is driving me nuts!

app.xaml.cs

    private readonly ServiceProvider _serviceProvider;
    public App()
    {
        ServiceCollection services = new ServiceCollection();
        ConfigureServices(services);
        _serviceProvider = services.BuildServiceProvider();
    }

    private void ConfigureServices(ServiceCollection services)
    {
        services.AddSingleton<MainWindow>();
        // Services
        services.AddSingleton<ICustomerService, CustomerService>();
        // ViewModels
        services.AddScoped<MainViewModel>();
        services.AddScoped<CustomerViewModel>();
        services.AddScoped<CustomerAddViewModel>();
        services.AddScoped<CustomerEditViewModel>();
        services.AddScoped<ServiceViewModel>();
    }

    private void OnStartup(object sender, StartupEventArgs e)
    {
        var mainWindow = _serviceProvider.GetService<MainWindow>();
        mainWindow.DataContext = _serviceProvider.GetService<MainViewModel>();
        mainWindow.Show();
    }

MainViewMode.cs

public class MainViewModel : ViewModelBase
{
    private CustomerViewModel _customerViewModel;
    private CustomerAddViewModel _customerAddViewModel;
    private CustomerEditViewModel _customerEditViewModel;

    private ViewModelBase _selectedViewModel;
    public ViewModelBase SelectedViewModel
    {
        get => _selectedViewModel;
        set
        {
            _selectedViewModel = value;
            NotifyPropertyChanged();
        }
    }

    public RelayCommand CustCommand { get; set; }
    public RelayCommand ServCommand { get; set; }

    **public MainViewModel(
        CustomerViewModel customerViewModel,
        CustomerAddViewModel customerAddViewModel,
        CustomerEditViewModel customerEditViewModel)
    {
        _customerViewModel = customerViewModel;
        _customerAddViewModel = customerAddViewModel;
        _customerEditViewModel = customerEditViewModel;
        CustCommand = new RelayCommand(OpenCustomer);
    }**

    private void OpenCustomer()
    {
        SelectedViewModel = _customerViewModel;
    }

}

CustomerViewModel

    public class CustomerViewModel : ViewModelBase
    {
    private ICustomerService _repo;
    private ObservableCollection<Customer> _customers;
    public ObservableCollection<Customer> Customers
    {
        get => _customers;
        set
        {
            _customers = value;
            NotifyPropertyChanged();
        }
    }

    public CustomerViewModel(ICustomerService repo)
    {
        _repo = repo;
    }

    public async void LoadCustomers()
    {
        List<Customer> customers = await _repo.GetCustomers();
        Customers = new ObservableCollection<Customer>(customers);
    }

    
}
like image 451
Laycoonz Avatar asked Oct 23 '25 02:10

Laycoonz


2 Answers

You're using constructor injection, which is only one of the ways to do DI. Another method is property injection, where you typically do something like this:

public class ClassToBeInjected
{
    [Inject]
    public SomeDataType PropertyToBeInjected {get; set;}

   ... etc ...
}

So long as ClassToBeInjected is being created via the DI framework, any properties tagged with [Inject] will also be injected automatically. Furthermore, any properties of SomeDataType that are tagged with the [Inject] attribute will also be injected, and so on down the heirarchy.

The exact mechanism of how this is achieved will depend on your DI framework. I've used the [Inject] attribute here, which is what Ninject uses, but each framework will have its own way of doing it.

like image 172
Mark Feldman Avatar answered Oct 25 '25 15:10

Mark Feldman


You don't need to pass all your dependencies to MainViewModel, now it's easy because you only have three, what if they were 20? I think the best thing to do here is to inject the dependency container and get all your view models from there.

public class MainViewModel : ViewModelBase
{
    private ServiceProvider _serviceProvider;

    public MainViewModel(IServiceProvider provider)
    {
        _serviceProvider = provider;
    }

    private void SomeMethod()
    {
        CustomerViewModel viewModel = _serviceProvider.GetRequiredService<CustomerViewModel>();
    }
}
like image 20
Enmanuel G Avatar answered Oct 25 '25 15:10

Enmanuel G