MVVM - Должно ли Представление содержать ссылку на Presenter / ViewModel?
Вопрос
Я просматривал образцы PRISM 2 в поисках идей о том, как наилучшим образом подойти к новому приложению, над которым я работаю, которое будет приложением PRISM 2 / WPF.Рассматривая, в частности, пример приложения для внедрения представления, которое поставляется с PRISM, я заметил, что все представления реализуют интерфейс, который позволяет presenter (или ViewModel) взаимодействовать с представлением.
В прошлом я делал это наоборот, я вводил presenter в представление, чтобы представление могло напрямую вызывать методы в presenter примерно так:
public partial class SomeView : ModuleBase
{
private ISomePresenter _somePresenter;
public SomeView (ISomePresenter somePresenter):this()
{
// Give the view a reference to the presenter
_somePresenter = somePresenter;
// Bind the View to the presenter
DataContext = _somePresenter;
}
private void btnSubmit_Click(object sender, RoutedEventArgs e)
{
// The view can call actions directly on the presenter (OK I should probably use a command for this)
_somePresenter.SomeAction();
}
}
Описанная выше техника показалась мне достаточно разумной, но, глядя на образцы, я начинаю сомневаться в этом подходе.Есть ли у кого-нибудь мнения (без каламбура) о наилучшем способе решения этой проблемы?
- Добавьте презентатора в представление и заставьте представление взаимодействовать с презентатором
- Добавьте представление в presenter и заставьте presenter взаимодействовать с представлением
- Что-то совершенно другое, о чем я еще не подумал?
Решение
Я думаю, что все это дело вкуса.Лично мне нравится, как вы видите это в образцах, на которые смотрите.У IView есть один метод, это SetViewModel(...).IViewModel имеет свойство, называемое View типа Object, которое по существу возвращает созданный DI экземпляр IView.
Причина, по которой мне нравится этот способ, заключается в том, что я почти всегда хочу сначала создать ViewModel, и я хочу никто в коде, чтобы иметь возможность делать что угодно с моим IView, за исключением получения ссылки на экземпляр (для внедрения представления или привязки представления, скажем, к ContentControl), поэтому его тип object .Если какому-либо коду нужно связаться с Представлением, для меня это всегда происходит через виртуальную машину ... и даже тогда представление обновляется обычно через привязку.Было бы странно переходить из View-> ViewModel-> UpdateBinding-> View, чем это есть, VM-> UpdateBinding-> View
Чтобы ответить на вопрос, мне обычно не нужна ссылка на presenter в codebehind.Обычно я могу справиться с этим с помощью команд из представления, привязанного к виртуальной машине.В некоторых случаях вы можете захотеть сохранить ссылку на presenter, чтобы сделать то, что у вас есть в вашем примере, но этого можно избежать, учитывая правильный набор инструментов (усложняет SL то, что в нем нет встроенных команд).
Как я уже сказал, все это дело вкуса...
-Jer
Другие советы
Наиболее распространенный подход к сопоставлению ViewModel с представлением в MVVM заключается в использовании DataTemplate
:
<DataTemplate DataType="{x:Type vm:SomeViewModel}">
<v:SomeView />
</DataTemplate>
Когда вы отображаете экземпляр ViewModel в ContentControl или ItemsControl, WPF автоматически создаст экземпляр соответствующего представления для ViewModel и установит для представления DataContext
к экземпляру ViewModel.
Таким образом, у вас нет никакой ссылки на представление в ViewModel, и Представление ссылается только на ViewModel через DataContext
собственность.В случае, если вам действительно нужно получить доступ к ViewModel в коде представления, вы всегда можете привести DataContext
(но это подразумевает, что представление знает о фактическом типе ViewModel, который вызывает связь)