WPF / MVVM Навигация с дочерними моделями представления, имеющими зависимости - PullRequest
0 голосов
/ 22 ноября 2018

Я пытаюсь использовать шаблон MVVM и шаблон Dependency Injection в своем приложении WPF MDI.Я использую первый подход к виртуальной машине.

По сути, мое приложение начинается с класса App.xaml.cs, который, если я правильно понял, должен быть моим корнем композиции (где разрешены все зависимости),Вот пример:

    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {          
            base.OnStartup(e);
            ...
            var login = new LoginView();
            login.DataContext = new LoginViewModel(Dependency1, Dependency2);

            loginView.ShowDialog();

            if (loginView.DialogResult.GetValueOrDefault())
            {
                 var app = new     MainWindow();
                 var mainVM = new MainViewModel(Dependency3, Dependency4);
                 app.DataContext = mainVM;
                 app.Show();
            }
        }
    }

Пока проблем нет, я могу разрешить зависимости как для LoginViewModel, так и для MainViewModel, использую ли я DI-контейнер или Dependency Injection вручную.Теперь давайте углубимся в MainViewModel.

Я был вдохновлен подходом Рэйчел Лим и использовал свойство SelectedViewModel, чтобы получить / установить используемый в настоящий момент ViewModel, который привязан к его View с использованием DataTemplates.Я позволю вам взглянуть на ссылку для более подробной информации о процессе, поскольку он совершенно не связан с моей проблемой здесь.Важно то, что мой MainViewModel отвечает за переключение ViewModel при необходимости.Но у моих детей ViewModels есть зависимости.Вот упрощенный пример:

     class MainViewModel
     {

            private ViewModel1 vm1;
            private ViewModel2 vm2;                

            public MainViewModel(Dependency1, Dependency2)
            {
                 ...
            }

            ...

            // Method used by an ICommand to display the ViewModel1's associated View
            private void DisplayView1() 
            {
                 vm1 = new ViewModel1(Dependency3, Dependency4, Dependency5);

            // Method used by an ICommand to display the ViewModel2's associated View
            private void DisplayView2() 
            {
                 vm2 = new ViewModel2(Dependency3, Dependency6);
                 SelectedViewModel = vm2;
            }
            ...
     }

Как видите, некоторые зависимости разделены между несколькими дочерними моделями представления, а некоторые нет.Моя проблема в том, что у меня проблемы с введением тех из корня композиции.До сих пор я нашел только два решения:

  • Наличие двух составных корней (своего рода): разрешение LoginViewModel и MainViewModel в App.xaml.cs и дочерних ViewModels в MainViewModel.Это подразумевает, при использовании контейнера IOC, ссылку на контейнер в обоих классах.
  • Передача дочерних ViewModels в качестве параметра конструктора MainViewModel и обработка их как любых других зависимостей.Моя проблема с этим подходом состоит в том, что если у меня, скажем, десять ViewModels, конструктор MainViewModel станет огромным.

Я прочитал, что можно передать фабрику MainViewModel и передать ответственностьсоздайте для него дочерние ViewModels, но я не видел ни одного примера, использующего дочерние ViewModels с параметрами конструктора.

Я не понимаю, как я мог бы использовать этот метод, не передавая все дочерние зависимости конструктору MainViewModel и, следовательно, не делая его снова огромным.

Может быть, я что-то не вижу,но мне это кажется тупиком.

Пожалуйста, помогите мне понять это правильно и покажите мне правильное направление.

Спасибо.

1 Ответ

0 голосов
/ 24 ноября 2018

Я только что понял, что до сих пор неправильно понимал всю эту фабричную вещь.

На самом деле, контейнер DI, который я использую, Ninject, имеет расширение, которое решает ту же проблему, что и я.Это расширение нуждается в интерфейсе, содержащем методы для создания необходимых зависимостей (в моем случае ViewModels) и создания конкретной фабрики за кулисами.Я просто неправильно использовал его, думая, что мне нужно каким-то образом передать все зависимости интерфейсу, в то время как он может разрешать сами ViewModels, поскольку они уже зарегистрированы в контейнере.

Итак, все, что у меня есть, - это один корень композиции(мой App.xaml.cs), где контейнер разрешает LoginViewModel и MainViewModel.Последний имеет фабричный интерфейс как зависимость, которая используется для разрешения всех дочерних ViewModels, а также разрешается контейнером.Никаких дополнительных ссылок на контейнер не требуется!

Большое спасибо Coops за вашу помощь!Вы определенно поставили меня на правильный путь!

...