2009-01-09 28 views
12

Me estoy divirtiendo al tratar 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 :).MVP y UserControls y la invocación

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 (forma) Presentador necesita saber acerca de la UC Presentador, pero estoy pensando que no sabe nada acerca de cómo la vista se compone. 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 mis suposiciones anteriores correctas? ¿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 el presentador de formulario invoque el Presentador de UC y tenga algún mecanismo para indicarle a 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 mucho gusto.

- nwahmaet

Respuesta

12

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 vista dogmática de cómo deben separarse las cosas. Parece que esta es una de las razones por las que Martin Fowler decidió probar el patrón clarify the terminology around the MVP.

Mi sabor favorito de MVP es el passive view, por lo que mi respuesta se basa en eso.

Implemento controles de usuario compuestos y formas muy a menudo utilizando el patrón de vista pasiva. Básicamente, hay 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.

+1

Me encantaría un ejemplo de código de configuración 3. – Llyle

+0

Si se pudiera proporcionar uno que sería encantador.Me resulta muy difícil encontrar detalles sobre cómo implementar patrones de MVP en winforms más complicados ... –

+0

Tengo un problema similar con los controles de usuario en formularios web. La página y cada control de usuario tienen sus propios presentadores distintos y desconectados. Es muy posible que cada presentador cargue la misma entidad de datos subyacente. Aunque el patrón tiene una excelente reutilización de código, obviamente golpea la base de datos más de lo necesario. – Junto

0

Sus preguntas es general de que una variedad de esquemas podría aplicarse.

En este caso, mi conjetura es que usted debe buscar en patrón de observador.

tenemos una interfaz que cualquier cosa que utiliza este punto de vista sería implementar. 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.

Por último recordar el control de usuario NO es la vista, pero la puesta en práctica 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.

4

he estado corriendo en contra de este problema exacto durante varios meses en una aplicación 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é ocurre dentro de la implementación de la vista, lo que significa que el presentador de la ventana no debe saber el presentador del control de usuario, y por lo tanto no debería haber comunicación entre ellos, incluida la instanciación de este último por parte del primero. 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 que 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, deben 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".

Su 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 saber sobre el modelo para pasar información al presentador del control.

Lo que esto hace efectivamente es separar 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.

+1

Estoy de acuerdo en que todas las UC son específicas de la implementación de la vista, pero también sienten que necesitan su propio presentador o modelo, dependiendo de lo que la UC pretende hacer. Un panel de navegación puede tener lógica Presenter en lugar de un Modelo; un código postal sin duda necesita un modelo de búsqueda. – nwahmaet

+1

Entiendo tu punto. Mi sensación es que debe evitarse unir un control personalizado a su modelo siempre que sea posible. Los controles que están vinculados a la arquitectura de su aplicación de esta manera los llamo controles "gordos". Son como mini ventanas secundarias y son MUY difíciles de manejar, manteniendo el diseño limpio/simple. –

Cuestiones relacionadas