2009-02-10 15 views
7

Editar: ¡Respondió la respuesta de Chris Holmes, pero siempre listo para refactorizar si alguien viene con una mejor manera! ¡Gracias!Presentador de vista de modelo, ¿cómo pasar entidades entre vista?

Haciendo algunas formas de ganar con MVP, ¿cuál es la mejor manera de pasar una entidad a otra vista.

Digamos que tengo un CustomerSearchView/Presenter, en doubleClick Quiero mostrar el CustomerEditView/Presenter. No quiero que mi vista sepa sobre el modelo, por lo que no puedo crear un ctor que tome un ICustomer en los parámetros.

mi reflejo sería,

CustomerSearchView crear un nuevo CustomerEditView, que crean su propio presentador. Entonces mi CustomerSearchView haría algo como:

var customerEditView = new CustomerEditView(); 
customerEditView.Presenter.Customer = this.Presenter.SelectedCustomer; 

Otro posible enfoque sería una clase CustomerDTO, y crea un CustomerEditView que aceptar uno de los CustomerDTO, pero yo creo que es un montón de trabajo algo sencillo.

Lo siento por la pregunta básica pero todo ejemplo que puedo encontrar nunca llegan a ese punto, y es un proyecto Brownfield, y el enfoque utilizado hasta ahora me está dando dolor de cabeza ...

Respuesta

4

No sé exactamente cómo estás mostrando tus puntos de vista, por lo que es un poco difícil darte consejos específicos aquí. Así es como he hecho este tipo de cosas antes:

Lo que hicimos fue hacer que CustomerSearchViewPresenter desencadenara un evento como OpenCustomer (customerId). (Eso supone que su vista de búsqueda solo tiene algunos datos del Cliente y el ID del cliente sería uno de ellos. Si su vista de búsqueda tiene objetos completos del Cliente en la lista, entonces podría llamar a OpenCustomer (cliente). Pero yo no construiría un buscar y permitir que se llene con objetos enteros ... Mantenemos nuestras vistas de búsqueda ligeras en términos de datos.)

En algún otro lugar de la aplicación hay un controlador de eventos que escucha el evento OpenCustomer() y realiza la tarea de crear un nuevo CustomerEditView w/Presenter (y voy a diferir a mi contenedor de IoC para hacer esto, así no tengo que usar la palabra clave "nueva" en ninguna parte). Una vez que se crea la vista, podemos pasar el id (u objeto del cliente) al nuevo CustomerEditView y luego mostrarlo.

Esta clase que se encarga de listar el evento OpenCustomer() y realiza la creación de CustomerEditView suele ser una clase de controlador en nuestra aplicación.

Para simplificar aún más esta situación, he hecho esto de otra manera: puedo crear tanto el CustomerSearchView (& presentador) y CustomerEditView (& presentador) cuando la aplicación o módulo se inicia. Cuando CustomerSearchView necesita abrir un cliente para su edición, CustomerEditView se convierte en el respondedor del evento OpenCustomer y carga los datos en sí mismo, y sabe cómo mostrarse en el contenedor que se supone que debe hacer.

Así que hay varias maneras de hacerlo.

+0

Creo que los eventos son un buen enfoque para este problema y, como dijiste en conjunto con un IoC, hace un código muy limpio. – pmlarocque

1

¿Qué tal:

//In CustomerSearchPresenter 
var presenter = new CustomerEditPresenter(); 
var customerEditView = new CustomerEditView(presenter); 
presenter.SetCustomer(customer); 

//In CustomerEditPresenter 
public void SetCustomer(customer) 
{ 
    View.Name = customer.Name; 
    View.Id = customer.Id; 
    ... 
} 

Al pensar que la vista de búsqueda del cliente solo debe delegar en su presentador, debe ejecutar una acción.

+0

Ha escrito mal "presentador" como "presneter", arriba. –

+0

bueno, casi como dije, excepto que utiliza un método en lugar de una propiedad para configurar el cliente. Gracias. – pmlarocque

+0

La diferencia está en quién tiene qué responsabilidades. En su configuración de ejemplo, el código de vista del cliente implica que la vista sabe cómo obtener un cliente. Eso debería dejarse al presentador. –

0

Hay un par de información crucial para conseguir un flujo natural en cualquier código de MVP:

  1. Es el presentador que impulsa a la vista, y no al revés.
  2. Debido a 1. la vista no necesita saber sobre la existencia del presentador. Menos dependencias generalmente significa un mantenimiento más fácil.

En C#, encuentro que los eventos son una gran ventaja al desacoplar presentadores de vistas. Más detalles en una respuesta anterior: Model-View-Presenter in WinForms

+0

Incorrecto. En MVP, una vista puede conocer la existencia del presentador. En muchos escenarios, la vista crea su presentador. – dzendras

+1

@dzendras: Primero, no dije que una vista ** no puede ** saber sobre la existencia del presentador. Dije que una vista ** no necesita ** saber sobre la existencia del presentador. Esa es una gran diferencia y reconoce que ** puede ** reducir las dependencias. En segundo lugar, sí, la vista ** puede ** crear su presentador, pero incluso cuando ese es el caso, sigue siendo el presentador el que impulsa el comportamiento de la vista, y no al revés. –

+0

Lo siento, no te he entendido bien. Estoy de acuerdo contigo completamente entonces :) – dzendras

0
  1. Me gustaría ver MS Prisma 4, y su agradable interfaz de navegación. Consulte también Silverlight y WCF Navigation. Están bien hechos y manejan cosas como solicitar al usuario la confirmación de formularios "sucios", con cancelación.

  2. Me gustaría ver la documentación PageFunction() en WCF también, para la forma de "llamada" una página de otro, y volver información.

Así es como funciona (Javascript, lo siento):

usuario hace doble clic en la lista de clientes del cliente:

CustomerList.onDblClick(customerId){ 

    app.fireEvent('customerEditRequest', id) 

} 

...

app.onCustomerEditRequest(id){ 
    this.mainRegion.requestNavigate('customers/edit', id); 
} 

Si la navegación a la vista de edición fue exitosa ...

CustomerEditView.onNavigatedTo(context){ 
    this.model.load(context.parameters.id)); 
} 

CustomerEditView.onSaveButtonClick(){ 
    this.model.save(); 
    app.fireEvent('customerEdited', id); 
} 

...

app.onCustomerEdited(id){ 
    app.mainRegion.requestNavigate('customerlist', id); 
} 

Hay algunas maneras diferentes que usted podría hacerlo:

  1. enviar una llamada de retorno a la forma de edición, desde la lista de clientes. El formulario de edición lo llamará y hará lo que quiera cuando se llame.

  2. tienen el formulario de edición de aumento en el evento "customerEdited" que se escucha y reacciona a (sin bus de toda la aplicación)

  3. utilizan un bus de eventos en toda la aplicación para gestionar los eventos en el centro, que se muestra.

0

Solía ​​hacer que mis vistas se comunicaran con sus presentadores, pero se han alejado de eso. No se ajusta a la definición original de un patrón (no es una razón en sí misma para desviar solo un factor contribuyente para obtener esos beneficios). Las vistas idealmente deberían mantenerse tan tontas y con la menor cantidad posible de dependencias. La vista debe comunicarse con el presentador (cualquier "observador") a través de delegados/eventos/algún mecanismo de "disparar y olvidar". De hecho, introduje un controlador en MVP específicamente para interceptar eventos de visualización y volver a disparar al presentador (raramente) para comunicarse con Presenter, o para comunicarme con un sistema o un bus de eventos específico para el presentador, lo que me permite para cambiar los mecanismos de alerta de acción del usuario sin tocar la vista. Sin embargo, debes tener cuidado con un autobús de eventos; muy pronto empiezas a lanzar todos los eventos allí, la aplicación se vuelve parlanchina en el manejo de eventos y los eventos no son los más rápidos en .Net.Sunchronization es una preocupación adicional, especialmente si su aplicación necesita tener una interacción más "conversacional" con su usuario.

Debe tener en cuenta que, si bien el presentador es usualmente visual/específico del proceso, las vistas (y los modelos de vista) pueden reutilizarse; tener la vista en una relación de contención/delegación con el presentador une fuertemente/limita su reutilización. Esto podría ser reducido por algunos DI, pero considero que los contenedores DI son complejidad innecesaria en la mayoría de los casos (ya que tengo que saber cómo crear objetos de todos modos y con qué frecuencia cambian un objeto por otro semánticamente similar después de crearlo o probarlo). ?). La dependencia concreta no va a ninguna parte excepto otra capa/agrega más oscuridad/hace que las cosas sean más difíciles de depurar/rastrear. Sin embargo, he estado en una patada de "simplicidad" últimamente y prefiero hacer mis creaciones de Fábrica/objeto/correlaciones de ORM para la mayoría de las aplicaciones, ya que usualmente hay tablas/entidades de BD de "1 a 1" por segundo y n necesidad del agregado complejidad de una herramienta ORM genérica de terceros que por contexto genérico/necesidad de servir diferentes aplicaciones tiene que hacer las cosas más difíciles de lo que deben ser, incluso si usted entiende cómo funcionan (no es el punto).

Por otra parte, sigue siendo bastante factible para View observar el modelo en MVP (como en MVC), por lo que no sería tan rápido para descartar esto. No prefiero hacer esto yo mismo, pero "no" rompe "el patrón. De hecho, desarrollé algo similar a MVP hace aproximadamente una década porque no me gustaba el "bucle circular" por cierto los componentes MVC (Ver saber sobre Model); Prefería tener la separación más limpia por vista y modelo que profesaban todos estos patrones (incluido el MVC), así como el deseo de mantener a View tan tonto como fuera posible (observar el modelo significaba que la vista necesitaría más inteligencia para procesar los cambios del modelo). Lo que terminé haciendo fue algo así como MVVM y el patrón de estrategia, donde utilicé las "subestructuras" del modelo para pasar a la Vista, sirviendo como "notificadores de cambio". Esto mantuvo todo el contenido específico y flexible/reutilizable (combinación difícil).

Cuestiones relacionadas