Как создать окно из ViewModel в свободно связанном приложении? WPF

У меня есть три проекта - "Bootstrapper", "ApplicationView" и "Presentation".

  • Проект «Bootstrapper» имеет файл app.xaml.cs, который запускает MainWindow
  • В проекте "ApplicationView" есть только необходимые окна - MainWindows.xaml, PersonWindow.xaml, SchoolWindows.xaml.
  • Проект «Презентация» имеет классы ViewModels и интерфейсы.

В моей модели просмотра я хочу отозвать окно. Но где я должен создать объект окна? Я прочитал статью о том, что я должен создать все экземпляры классов в файле App.xaml.cs. Но как вызвать этот объект в App.xaml.cs из viewModel? Я не могу создавать объекты в классах ViewModel, так как не могу добавить ссылку «BootStrapper» в «Презентацию», потому что VS 2010 выдает ошибку: «Добавление этого проекта в качестве ссылки вызовет циклическую зависимость».

App.xaml.cs проекта "Bootstrapper":

    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        ComposeObjects();
        Application.Current.MainWindow.Title = "Loose Coupling - People Viewer";
        Application.Current.MainWindow.Show();
    }

    private static void ComposeObjects()
    {
        //MainWindow
        var repository = new ServiceRepository();            
        var viewModel = new PeopleViewerViewModel(repository);
        Application.Current.MainWindow = new MainWindow(viewModel);
        //SuperWindow
        var salut = new ServiceSalutation();
        var salutViewModel = new SuperWindowViewModel(salut);
        var NewForm = new SuperWindow(salutViewModel);
    }

MainWindowViewModel.cs проекта "Презентация":

    void NewForm(object parameter)
    {
        //New Window
        /*/var salut = new ServiceSalutation();
        //var salutViewModel = new SuperWindowViewModel(salut);*/
        //var NewForm = new SuperWindow();
        How can I revoke a SuperWindow.xaml from a project "ApplicationView"?
    }

Как вызвать SuperWindow.xaml проекта «Презентация» из MainWindowViewModel.cs проекта «Презентация»? Я не могу добавить ссылку на «BootStrapper» в «Презентацию», потому что VS 2010 выдает ошибку: «Добавление этого проекта в качестве ссылки вызовет циклическую зависимость».


person StepUp    schedule 21.03.2014    source источник
comment
Это выглядит противно. Я бы провел рефакторинг кода и внедрил бы инфраструктуру MVVM, такую ​​как Claiburn.Micro et al. Вы можете настроить представление для просмотра менеджера моделей самостоятельно, но в этом нет реального смысла, если вы не изучаете MVVM с нуля...   -  person MoonKnight    schedule 21.03.2014
comment
@Killercam, да, я изучаю сцепку вшей с нуля, но у меня нет проблем с созданием новых окон в простом MVVM. Более того, этот код является примером слабой связанности команды plyralsight.   -  person StepUp    schedule 21.03.2014
comment
Тут мне сложно советовать, так как это, скорее всего, будет нетривиальное решение...   -  person MoonKnight    schedule 21.03.2014
comment
Однажды я развернул свой собственный фреймворк MVVM, и я справился с этим так, чтобы иметь службу, в которой модели представления были зарегистрированы со связанными представлениями (окнами), а модели представления могли иметь зависимость от этой службы (это был синглтон). Затем модель представления или ваш загрузчик может попросить службу создать представление для предоставленной ей модели представления, и служба создаст экземпляр и покажет окно, а также установит свойство DataContext.   -  person Steve    schedule 21.03.2014


Ответы (1)


Я действительно не совсем понимаю нашу проблему, но я предполагаю, что вы пытаетесь создать, а затем открыть окна из своей модели просмотра. Это может быть ответом. В вашей ViewModel поместите делегат action или func для выполнения необходимых вам внешних действий. вы можете передать его в конструктор вашей модели просмотра, возможно, так.

Action newFormAction = () => {
       var salut = new ServiceSalutation();
       var salutViewModel = new SuperWindowViewModel(salut);
       var newForm = new SuperWindow(salutViewModel);
       newForm.Show();
   };

var viewModel = new PeopleViewerViewModel(repository, newFormAction);

затем в вашей модели просмотра вы можете вызвать действие для создания всплывающего окна без необходимости ссылки на уровень представления

person Dean Chalk    schedule 21.03.2014
comment
Это было бы нарушением MVVM, поскольку ваша ViewModel зависит от конкретной реализации представления... чего и следует избегать MVVM. Правильный способ обработки окон/представлений - через внедрение зависимостей (привяжите представление к ViewModel в вашем загрузчике, таким образом вы не загрязняете свою ViewModel зависимостями. Или используйте ViewLocator/Service или для более сложных вещей NavigationService - person Tseng; 21.03.2014
comment
Это не нарушение MVVM для передачи делегатов действий или функций. - person Dean Chalk; 21.03.2014
comment
@DeanChalk, но я не могу добавить ссылку на SuperWindow.xaml, поэтому мои классы ViewModel не могут видеть файлы Windows.xaml. - person StepUp; 21.03.2014
comment
если вы хотите открыть представление из своей модели представления, это лучший способ сделать это, не нарушая MVVM. Если вы хотите взаимодействовать со своим представлением через модель представления, предварительно привяжите представление к той же модели представления. - person Dean Chalk; 21.03.2014
comment
может быть, вы знаете несколько хороших примеров слабосвязанных приложений, в которых одно окно заменяет другое окно? некоторые ссылки будут очень полезны. - person StepUp; 21.03.2014
comment
@DeanChalk, где я должен написать код, чтобы изменить представление? Модель просмотра? - person StepUp; 22.03.2014