winforms design-patterns user-interface mvp

winforms - MVP y UserControls e invocación



design-patterns user-interface (3)

Sus preguntas son generales de que podrían aplicarse una variedad de esquemas.

En este caso, mi suposición es que deberías mirar el patrón del observador.

Usted tiene una interfaz que cualquier cosa que use esa vista implementaría. Luego se registraría cuando la aplicación se inicializa con una colección de esas interfaces. Cualquier comando que necesite actualizar esa vista atravesará la colección y notificará que cada vista debe actualizarse.

A diferencia de los ejemplos típicos, las vistas serían Controles del usuario. Tiene la flexibilidad de hacer que cualquier elemento de UI implemente esa interfaz para que pueda usar diálogos, formularios completos, etc. además de su Control de usuario.

Finalmente, recuerde que el Control de usuario NO es la vista, sino la implementación de la Vista. Cualquiera que sea el esquema que adopte, puede definir qué Vista es lo más profunda que desea y hacer que el Control de usuario implemente esa interfaz.

Me estoy divirtiendo tratando de entender algo de MVP stuf, ya que pertenece a User Controls. Estoy usando .NET WinForms (o algo parecido) y el patrón Supervisor Controlador (bueno, creo que soy :).

El control de usuario es en sí mismo parte de una aplicación MVP (es la vista y tiene un presentador asociado, etc.). El presentador siempre se inicia primero, y comienza el modelo (s) y luego la vista (s). The View construye su UI, parte de la cual será NUEVA a la UC, que es la Vista.

Ahora el Presentador (de formulario) necesita saber sobre el Presentador de UC, pero estoy pensando que no sabe nada sobre cómo se compone la Vista. El formulario Presenter no sabe, por ejemplo, que la UC forma parte de la colección de controles del formulario, ni debería hacerlo.

Además, la experiencia de diseño no debe cambiarse; IOW el desarrollador de la Vista (formulario) solo debe poder seleccionar un Control de usuario de la caja de herramientas y soltarlo en un formulario.

Por lo tanto, a mis preguntas. En primer lugar, ¿son correctas mis suposiciones? ¿Algo equivocado? ¿Hecho un desastre? WTF estás pensando?

En segundo lugar, ¿es correcto (¿es suficiente?) Que el formulario Vista invoque la Vista de UC, y que el Presentador de formularios invoque el Presentador de UC y tenga algún mecanismo para indicarle a la Vista de UC cuál es su Presentador. Esto rompe mi regla de "Presentador primero", pero no estoy seguro de cómo hacerlo.

Cualquier otro pensamiento, sugerencia o comentario aceptado con gusto.

- nwahmaet


He estado enfrentando este problema exacto durante varios meses en una aplicación en la que estoy trabajando. La conclusión a la que he llegado recientemente es que en muchos casos podría ser imposible aplicar el patrón MVP tanto en la ventana como en los niveles de control del usuario, sin "romper" el patrón.

Mi idea es que el control del usuario es parte de la implementación de la vista, y el presentador no debe saber qué está sucediendo dentro de la implementación de la vista, lo que significa que el presentador a nivel de ventana no debe conocer al presentador del control del usuario. y, por lo tanto, no debería haber comunicación entre ellos, incluida la ejemplificación de esta última por parte de la primera. Se podría argumentar que el presentador del control de usuario es parte de la implementación de la vista de ventana, por lo que la vista de ventana puede crear una instancia del presentador de control de usuario. Pero no puede inyectar las clases modelo que el presentador necesita, porque se supone que la vista no debe estar al tanto de ellas.

La conclusión a la que creo llegar es que TODOS los controles de usuario son específicos de la implementación de vista, por lo que deben estar completamente dentro del silo de vista del patrón más grande. Como tal, no llegan a tener sus propios presentadores ... Al menos no se incluyen con la implementación de control en sí. En su lugar, deberían ser manipulados indirectamente por el presentador de la ventana principal, a través de los campos de paso expuestos en la interfaz de visualización. En resumen, el control del usuario está expuesto al presentador no por su propia interfaz, sino a través de una interfaz de paso común implementada por su vista principal. Llamar a esto una "interfaz de vista parcial".

El presentador puede contener instancias de una clase de presentador reutilizable que solo funciona con esta interfaz de vista parcial y las piezas relevantes del modelo. Esto le permitirá evitar volver a escribir el código del presentador para traducir del modelo cada vez que necesite usar el control, Y evita que la vista de ventana necesite conocer el modelo para pasar información al presentador del control.

Lo que esto hace efectivamente es que separa más el control del usuario, como un módulo, de su modelo de datos. Esto tiene sentido si piensa en un control de usuario, como un todo, como un elemento de la implementación de la vista. Como una unidad reutilizable, es una funcionalidad de vista parcial, y ninguna parte de ella debe estar vinculada a su modelo de datos.


Un presentador debe considerarse como "estado autónomo" en el nivel de presentación. Esto significa que es responsable de garantizar que la presentación de la vista del estado del modelo esté sincronizada. La razón por la que menciono esto es porque el "patrón" de MVP a menudo se pierde en la visión dogmática de cómo deben separarse las cosas. Parece que esta es una de las razones por las que Martin Fowler decidió tratar de aclarar la terminología sobre el patrón MVP .

Mi sabor favorito de MVP es la visión pasiva , por lo que mi respuesta se basa en eso.

Implemento los controles y formularios de usuario compuestos muy a menudo usando el patrón de vista pasiva. Hay esencialmente 3 configuraciones diferentes:

  1. Un presentador para todos los controles de usuario en la jerarquía. Acoplar la vista usando una interfaz.
  2. Un presentador para cada control de usuario en el árbol compuesto. Cada presentador principal es responsable de crear instancias e inicializar a sus presentadores secundarios. Los controles de usuario se crean en el momento del diseño, y pueden funcionar sin un presentador (sin comportamiento de presentación)
  3. Un presentador para cada control de usuario en el árbol compuesto. Todos los presentadores están vagamente acoplados a través de una clase de controlador de nivel superior. La clase de controlador es responsable de construir el presentador, conectarlo y coordinar sus eventos.

Aunque es una solución de último recurso para mí (debido a su complejidad), creo que la última opción es la solución que está buscando.