bueno, hay un tipo que escribió que lo utilizaba con winforms. Yo no le veo la utilidad ahí y no te lo aconsejaría.. El link que te pase es para entender los patrones mas que nada, los frameworks van y vienen... los patrones y las teorías son bastante menos efímeras.
MVP es algo que ni el propio Martín Fowler pudo terminar de explicar bien y lo termino dividiendo en dos patrones. Uno es el llamado Passive View y el otro es el llamado Supervising Controller.
Ambos pueden ser utilizados en Winforms.
Patrón Passive View
hay gente escéptica al databinding de winforms y prefiere utilizar Passive View. En este patrón la implementación del View puede ser mas liviana pero su interfaz tiende a ser mas pesada (más métodos). La característica mas importante de este patrón es que el VIEW no conoce ningún modelo, ni viewmodel, ni objetos de dominio, absolutamente nada.
El Presenter tiene que hacer más llamadas al view "seteando" o configurando cada uno de los controles de presentación, un ejemplo sencillo de esto podría ser... imaginate una pantalla para editar los datos del cliente, donde al principio hay que mostrar todos los datos del cliente y cuando el usuario aprieta el boton editar ... guardarlos. Una interfaz de view podría ser algo así:
public interface IEditCustomerView
{
void AgregarPaisAlCombo(string codigoIso, string nombrePais);
void SetNombre(string valor);
void SetApellido(string valor);
void SetCuit(string valor);
void SetPais(string codigoIso);
//****tal vez todos estos mismos Set como Gets....
event EventHandler GuardarClick;
event EventHandler CancelarClick;
}
Esta interfaz es lo que tu FORM tiene que implementar.
Luego el presenter podría tener esta forma:
public class EditarClientePresenter
{
public EditarClientePresenter(IEditarClienteView editarClienteView, IRepositorioCliente repositorioCilente, IRepositorioPaise ...){...}
public void Iniciar(int idCliente){
var cliente = repositorioCliente.Get(idCliente);
//obtener todos los paises recorrer uno por uno y llamar al view.AddCliente
editarClienteView.SetNombre(cliente.Nombre)..
editarClienteView.GuardarClick += GuardarCliente;
}
private void GuardarCliente(object sender, EventArgs args)
{
//obtener cliente, y para cada propiedad hacer cliente.Nombre = editarClietneView.GetNombre();
}
}
Patrón supervising controller
Este patrón aprovecha una infrastructura de databinding simple. La implementación del View puede ser un poco mas compleja, aunque en winforms no lo es ya que el databinding de winforms nos ayuda en este punto, la interfaz del view es mucho más sencilla y la implementación del presentar puede ser más sencilla también. En este patrón el view si conoce los modelos que nosotros queramos que conozca. Algunas personas pueden decir que en este patrón el View solo debería conocer de ViewModels o DTOs, otra visión más prágmatica es usar ViewModel y DTO cuando corresponda y tener la libertad de usar Objetos de dominio cuando uno lo desee.
Básicamente para el mismo caso de uso la interfaz del View podría ser así:
public interface IEditarClienteView
{
ClienteViewModel ClienteEnEdicion {get;set;}
IEnumerable<PaisViewModel> PaisesParaSeleccion {get;set;}
event EventHandler GuardarClick;
}
el presenter sería algo así:
public class EditarClientePresenter
{
public EditarClientePresenter(IEditarClienteView editarClienteView, IRepositorioClientes, IRepositorioPaises){...}
public void Iniciar(int clienteId){
editarClienteView.PaisesParaSeleccion = repositorioPais.OBtenerTodosOrdenadosPorNombre() .... Mapeo Objeto- ViewModel..
editarClienteView.ClienteEnEdicion = repositorioCliente.Get(clietneId)..... MAPEO OBJETO - VIEWMODEL. Puede ser manual o automapper.
editarClienteView.GuardarClick += GuardarClicked...
}
private void GuardarClicked(....)
{
var cliente = ... obetner el cliente con el id..
//mapear las propiedades del vm (editarClienteView.ClienteEnEdicion ) al objeto de dominio
//guardar
}
}
El form se arma con el designer, agregando un databinding... del tipo de objeto, apuntandolo a ClienteviewModel, luego con el mismo designer de datasources podes arrastrar cada control al formulario. En el formulario te van a quedar unos controles "clienteViewModelBindingSource1" algo así... En el código behind del form te quedaría basicamente algo así
public class FormEditarClienteView : Form... , IEditarClienteView
{
public ClienteViewModel ClienteEnEdicion
{
get{ return (ClienteViewModel)clienteViewModelBindingSource1.DataSource;}
set{ clienteViewModelBindingSource.DataSource = value}
}
public IEnumerable<PaisViewModel> Paises
{
get{return (IEnumerable<PaisViewModel>)paisViewModelBindingSource1.DataSource;
set{ paisViewModelBindingSource1.DataSource = value }
}
public event EventHandler GuardarClick
{
add{ botonGuardar.Click += value; }
remove{botonGuardar.Click -= value; }
}
}
Notas en general
Esta es mi interpretación de ambos patrones, puede ser que yo haya interpretado muy mal, decírmelo!
Siempre es importante recordar como uno llega a necesitar hacer esto, nunca hay que perder de vista la meta. Uno hace esto para separar las responsabilidades y de esa forma tener un código más limpio y fácil de testear. En general una pantalla es difícil de testear y todos estos patrones MVC, MVVM, MVP Passive View y Supervising controller nacieron por esa razón, por la razón de que testear la pantalla es difícil. Con cualquiera de los dos patrones que explique aca el presenter es muy sencillo de probar, y el view es muy sencillo de crear un mock o un stub. Lo mismo con el repositorio que use de ejemplo, aunque esta es solo una alternativa podría ser que ese repositorio fuera un webservice o cualquier otra cosa.
Fin
Perdón que me haya copado escribiendo, esto hubiera ido mejor seguramente en un blog... pero me salió así. Si alguien tiene ganas de ponerlo en un post o en algún otro lugar bienvenido sea!