В чем преимущество внедрения виртуальной машины в представление по сравнению с определением ее в XAML при использовании Prism?

#c# #.net #wpf #mvvm #prism

#c# #.net #wpf #mvvm #prism

Вопрос:

Обычно я определяю свои viewmodels непосредственно в XAML следующим образом:

 <Window.DataContext>
    <vm:MyViewModel />
</Window.DataContext>
 

В противном случае, когда ViewModel имеет параметр конструктора с ObjectDataProvider .

В официальной документации Prism 5 в формате pdf они определяют ее в codebehind и вводят viewmodel с помощью MEF / Unity следующим образом:

 [Export] 
public partial class Shell : Window 
{ 
    public Shell() { InitializeComponent(); } 

    [Import] 
    ShellViewModel ViewModel
    {
        set { this.DataContext = value; } 
    }
}
 

Я лично использую DI с MEF, но в этом конкретном случае я действительно не вижу никаких преимуществ от внедрения виртуальной машины и считаю это чрезмерным использованием DI.
(предположение: я не пишу никаких огромных модульных тестов для GUI, которые имитируют всю ViewModel, поскольку мои модульные тесты основаны науровень обслуживания. И даже в этом случае я мог бы динамически переключать DataContext в тестовом примере.).
Но, возможно, я что-то упускаю.

Итак, каковы плюсы / минусы между двумя подходами?

Комментарии:

1. Это не MVVM, когда представление знает ViewModel. Оба они слабо связаны. Одним из преимуществ является то, что вы можете использовать свой View для разных ViewModels.

2. @Rabban: пока вы не используете контейнер DI, представление всегда знает viewmodel, не имеет значения, определяете ли вы его в codebehind или в xaml. И поскольку я реализую INotifyPropertyChanged / ICommand и использую привязку данных для каждого свойства, это определенно MVVM. И, как я упоминал в своем посте, вы всегда можете динамически изменять DataContext в codebehind, даже если вы хотите использовать разные viewmodels для одного представления.

3. Вы можете реализовать MVVM без DI. Вам нужно 3 проекта для создания чистого решения MVVM. Один проект для ваших ViewModels, один для ваших представлений и один как Application StartProject, этот проект свяжет ваши представления с вашими моделями, а ViewModel и View Project не должны знать другого. Ваши ViewModels могут создавать новые экземпляры ViewModels, а ContentPresenter в вашем представлении может отображать для него правильное представление. Все, что работает без DI. CodeBehind, действительно не рекомендуется в MVVM. И, как я уже говорил, если представление знает модель, это не MVVM.

4. @Rabban: Я думаю, вы не поняли, что я имел в виду. Вы должны установить DataContext для представления либо в коде, либо в XAML (в MVVM это viewmodel). И это именно тот момент, когда view знает о viewmodel. Если вы знаете другой способ, вы можете представить его. То, о чем вы говорите, — это разделение слоев с проектами.

5. если вы имеете в виду, что он знает это во время выполнения, то вы правы. Но это не обязательно знать во время разработки. Вы можете достичь этого, разделив проекты, как я описал в моем другом комментарии. Вы можете использовать DataTemplates, и вашим представлениям никогда не нужно знать ViewModel во время разработки. Я могу привести вам дополнительные примеры, если вам интересно.

Ответ №1:

Существует много проблем, связанных с тем, что ваш View отвечает за создание ваших ViewModels, но я просто использую один в качестве примера; управление зависимостями. Предположим, у вас определена виртуальная машина:

 public class MyViewModel
{
    public MyViewModel() { }
}
 

Предположим, что ваше представление было создано в XAML:

 <Window.DataContext>
     <local:MyViewModel />
</Window.DataContext>
 

Итак, что вы делаете, когда вашей виртуальной машине требуется служба или зависимость?

 public class MyViewModel
{
    public MyViewModel(IMyService myservice) { }
}
 

Что еще хуже, что, если у этой службы есть собственные зависимости?

Что ж, теперь определение этого в XAML определенно невозможно по очевидным причинам. Если вы определяете DataContext в коде, у вас возникает аналогичная проблема, с которой вы столкнулись в XAML; управление зависимостями. Если бы вы внедрили ViewModel, вам никогда не пришлось бы беспокоиться о том, какие зависимости требуются вашей ViewModel, и вам никогда не пришлось бы изменять свой код, чтобы приспособить новую зависимость, добавленную к ctor виртуальной машины. Это просто сработало бы. Это особенно удобно, когда ваши виртуальные машины находятся в другой сборке и используются совместно на нескольких платформах, или когда вам нужно изменить, какую конкретную реализацию зависимости использовать, на основе конфигурации сборки или устройства.

Комментарии:

1. Предполагая, что моя viewmodel используется только из одного представления: будет ли по-прежнему неправильным определять viewmodel с параметром конструктора, как я добавил к вашему ответу?

2. ДА. Это не решает проблему управления зависимостями, и все становится более сложным при обработке одиночных элементов и зависимостей зависимостей. Кроме того, это чрезвычайно затрудняет изменение реализаций зависимостей.