MVVM - Caso o Vista tem uma referência para o Apresentador / ViewModel?
Pergunta
Eu estive olhando através do prisma 2 amostras para idéias sobre como melhor abordagem uma nova aplicação que estou trabalhando, o que será um prisma 2 / WPF aplicativo. Olhando em particular, a aplicação de exemplo Injection Ver que vem com o PRISM tenho notado que todos os pontos de vista implementar uma interface que permite que o apresentador (ou ViewModel) para interagir com o View.
No passado, eu fiz isso o oposto maneira redonda, eu injetar o apresentador na vista para que a exibição pode chamar diretamente a métodos em que o apresentador um pouco como este:
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();
}
}
A técnica acima bastante razoável pareceu-me, mas olhando para as amostras que estou começando a questionar a abordagem. Alguém tem de visualizações (sem trocadilhos) sobre a melhor maneira de fazer isso?
- Adicione o apresentador para a vista e obter o intuito de interagir com o apresentador
- Adicionar a vista para o apresentador e obter o apresentador para interagir com a visão
- Algo totalmente diferente que eu não tenha pensado ainda?
Solução
Eu acho que é tudo uma questão de gosto. Pessoalmente, eu gosto do jeito que você vê-lo em amostras que você está olhando. IView tem um método, isso é SetViewModel (...). IViewModel tem uma propriedade chamada Vista do tipo Object, que, essencialmente, retorna o DI instanciado IView.
A razão que eu gosto desta forma é quase sempre quer criar um ViewModel em primeiro lugar e eu quero ninguém no código para ser capaz de fazer qualquer coisa com o meu IView, com exceção de referência get à instância ( para injecção vista ou de ligação a fim de dizer um ContentControl), razão pela qual o seu tipo de objecto. Se qualquer código precisa falar com o Vista, para mim, é sempre através da VM ... e mesmo assim a visão é atualizado geralmente através de ligação. Ele se sentiria estranho para ir do Ver-> ViewModel-> UpdateBinding-> View, do que é, VM-> UpdateBinding-> Ver
Para responder à pergunta, eu geralmente não precisa de uma referência para o apresentador no codebehind. Normalmente eu posso lidar com isso com os comandos a partir da visão que está sendo ligado ao VM. Em alguns casos, você pode querer manter referência ao apresentador para fazer o que você tem no seu exemplo, mas é evitável dado o conjunto de ferramentas corretas (faz SL mais difícil que não têm construído em comandos).
Como eu disse, é tudo uma questão de gosto ...
-Jer
Outras dicas
A abordagem mais comum para mapear um ViewModel para um modo de exibição em MVVM é usar um DataTemplate
:
<DataTemplate DataType="{x:Type vm:SomeViewModel}">
<v:SomeView />
</DataTemplate>
Quando você exibir uma instância ViewModel em um ContentControl ou ItemsControl, WPF irá instanciar automaticamente o modo de exibição apropriado para o ViewModel, e definir DataContext
do Vista para a instância ViewModel.
Dessa forma, você não tem qualquer referência à exibição no ViewModel, ea vista única referencia o ViewModel através da propriedade DataContext
. No caso de você realmente precisa acessar o ViewModel em code-behind do Vista, você sempre pode lançar o DataContext
(mas isto implica que a exibição sabe sobre o tipo real do ViewModel, que induz o acoplamento)