Estoy tratando de implementar el método MVP por primera vez, usando WinForms.
Estoy tratando de comprender la función de cada capa.
En mi programa tengo un botón GUI que cuando se hace clic en él abre una ventana de diálogo abierto.
Entonces, usando MVP, la GUI maneja el evento de clic de botón y luego llama presenter.openfile ();
Dentro de presenter.openfile (), ¿debería eso delegar la apertura de ese archivo a la capa del modelo, o como no hay datos o lógica para procesar, debería simplemente actuar en la solicitud y abrir la ventana openfiledialog?
Actualización: he decidido ofrecer una recompensa ya que siento que necesito más ayuda en esto, y preferiblemente adaptado a mis puntos específicos a continuación, para tener contexto.
Bien, después de leer sobre MVP, he decidido implementar la vista pasiva. Efectivamente, tendré un montón de controles en un Winform que serán manejados por un Presentador y luego las tareas delegadas al Modelo (s). Mis puntos específicos están a continuación:
Cuando se carga el winform, debe obtener una vista de árbol. ¿Estoy en lo cierto al pensar que la vista debería llamar a un método como: presenter.gettree (), este a su vez delegará en el modelo, que obtendrá los datos para la vista de árbol, lo creará y lo configurará, lo devolverá al presentador, que a su vez pasará a la vista que luego simplemente lo asignará a, digamos, un panel?
¿Sería lo mismo para cualquier control de datos en Winform, ya que también tengo una vista de cuadrícula de datos?
Mi aplicación tiene varias clases de modelos con el mismo ensamblaje. También es compatible con una arquitectura de complementos con complementos que deben cargarse al inicio. ¿La vista simplemente llamaría a un método de presentador, que a su vez llamaría a un método que carga los complementos y muestra la información en la vista? Qué nivel controlaría las referencias de los complementos. ¿La vista tendría referencias a ellos o al presentador?
¿Estoy en lo correcto al pensar que la vista debe manejar todo lo relacionado con la presentación, desde el color del nodo de la vista de árbol hasta el tamaño de la cuadrícula de datos, etc.?
Creo que son mis principales preocupaciones y si entiendo cómo debe ser el flujo de estos, creo que estaré bien.
Respuestas:
Esta es mi humilde opinión sobre MVP y sus problemas específicos.
Primero , cualquier cosa con la que un usuario pueda interactuar, o simplemente mostrarse, es una vista . Las leyes, el comportamiento y las características de tal vista se describen mediante una interfaz . Esa interfaz se puede implementar utilizando una interfaz de usuario de WinForms, una interfaz de usuario de consola, una interfaz de usuario web o incluso ninguna interfaz de usuario (generalmente cuando se prueba un presentador); la implementación concreta simplemente no importa siempre que obedezca las leyes de su interfaz de vista .
En segundo lugar , una vista siempre está controlada por un presentador . Las leyes, el comportamiento y las características de dicho presentador también se describen mediante una interfaz . Esa interfaz no tiene interés en la implementación de la vista concreta siempre que obedezca las leyes de su interfaz de vista.
En tercer lugar , dado que un presentador controla su vista, para minimizar las dependencias realmente no hay ganancia en que la vista sepa algo sobre su presentador. Existe un contrato acordado entre el presentador y la vista y eso lo establece la interfaz de la vista.
Las implicaciones de Third son:
Para su problema, lo anterior podría verse así en un código algo simplificado:
interface IConfigurationView { event EventHandler SelectConfigurationFile; void SetConfigurationFile(string fullPath); void Show(); } class ConfigurationView : IConfigurationView { Form form; Button selectConfigurationFileButton; Label fullPathLabel; public event EventHandler SelectConfigurationFile; public ConfigurationView() { // UI initialization. this.selectConfigurationFileButton.Click += delegate { var Handler = this.SelectConfigurationFile; if (Handler != null) { Handler(this, EventArgs.Empty); } }; } public void SetConfigurationFile(string fullPath) { this.fullPathLabel.Text = fullPath; } public void Show() { this.form.ShowDialog(); } } interface IConfigurationPresenter { void ShowView(); } class ConfigurationPresenter : IConfigurationPresenter { Configuration configuration = new Configuration(); IConfigurationView view; public ConfigurationPresenter(IConfigurationView view) { this.view = view; this.view.SelectConfigurationFile += delegate { // The ISelectFilePresenter and ISelectFileView behaviors // are implicit here, but in a WinForms case, a call to // OpenFileDialog wouldn't be too far fetched... var selectFilePresenter = Gimme.The<ISelectFilePresenter>(); selectFilePresenter.ShowView(); this.configuration.FullPath = selectFilePresenter.FullPath; this.view.SetConfigurationFile(this.configuration.FullPath); }; } public void ShowView() { this.view.SetConfigurationFile(this.configuration.FullPath); this.view.Show(); } }
Además de lo anterior, normalmente tengo una
IView
interfaz base en la que guardo laShow()
vista del propietario o el título de la vista de la que suelen beneficiarse mis vistas.A sus preguntas:
1. Cuando se carga el winform, debe obtener una vista de árbol. ¿Estoy en lo cierto al pensar que la vista debería llamar a un método como: presenter.gettree (), esto a su vez delegará en el modelo, que obtendrá los datos para la vista de árbol, lo creará y lo configurará, lo devolverá al presentador, que a su vez pasará a la vista que luego simplemente lo asignará a, digamos, un panel?
2. ¿Sería lo mismo para cualquier control de datos en Winform, ya que también tengo una vista de cuadrícula de datos?
3. Mi aplicación tiene varias clases de modelos con el mismo ensamblaje. También es compatible con una arquitectura de complementos con complementos que deben cargarse al inicio. ¿La vista simplemente llamaría a un método de presentador, que a su vez llamaría a un método que carga los complementos y muestra la información en la vista? Qué nivel controlaría las referencias de los complementos. ¿La vista tendría referencias a ellos o al presentador?
4. ¿Estoy en lo cierto al pensar que la vista debería manejar todo lo relacionado con la presentación, desde el color del nodo de la vista de árbol hasta el tamaño de la cuadrícula de datos, etc.?
¿Qué pasa con los datos de los nodos en los que se hace clic?
5. Si cuando hago clic en los árboles, ¿debo pasar a través del nodo específico al presentador y luego, a partir de ahí, el presentador calculará qué datos necesita y luego le pide al modelo esos datos, antes de presentarlos de nuevo a la vista?
fuente
El presentador, que contiene toda la lógica en la vista, debe responder al botón que se hace clic como dice @JochemKempe . En términos prácticos, el controlador de eventos de clic de botón llama
presenter.OpenFile()
. El presentador puede entonces determinar qué se debe hacer.Si decide que el usuario debe seleccionar un archivo, vuelve a llamar a la vista (a través de una interfaz de vista) y deja que la vista, que contiene todos los aspectos técnicos de la interfaz de usuario, muestre el
OpenFileDialog
. Esta es una distinción muy importante en el sentido de que no se debe permitir al presentador realizar operaciones vinculadas a la tecnología de interfaz de usuario en uso.El archivo seleccionado se devolverá al presentador, que continúa con su lógica. Esto puede involucrar cualquier modelo o servicio que deba manejar el procesamiento del archivo.
La razón principal para usar un patrón MVP, en mi opinión, es separar la tecnología UI de la lógica de la vista. Por lo tanto, el presentador orquesta toda la lógica mientras la vista la mantiene separada de la lógica de la interfaz de usuario. Esto tiene el efecto secundario muy agradable de hacer que el presentador sea completamente comprobable.
Actualización: dado que el presentador es la encarnación de la lógica que se encuentra en una vista específica , la relación vista-presentador es, en mi opinión , una relación uno a uno. Y para todos los propósitos prácticos, una instancia de vista (por ejemplo, un formulario) interactúa con una instancia de presentador, y una instancia de presentador interactúa con una sola instancia de vista.
Dicho esto, en mi implementación de MVP con WinForms, el presentador siempre interactúa con la vista a través de una interfaz que representa las capacidades de la interfaz de usuario de la vista. No hay limitación sobre qué vista implementa esta interfaz, por lo tanto, diferentes "widgets" pueden implementar la misma interfaz de vista y reutilizar la clase de presentador.
fuente
El presentador debe actuar en la solicitud y mostrar la ventana openfiledialog como sugirió. Dado que no se requieren datos del modelo, el presentador puede y debe manejar la solicitud.
Supongamos que necesita los datos para crear algunas entidades en su modelo. Puede pasar el canal de transmisión a la capa de acceso donde tiene un método para crear entidades a partir de la transmisión, pero le sugiero que maneje el análisis del archivo en su presentador y use un constructor o un método Create por entidad en su modelo.
fuente