2011-04-20 27 views
7

Tengo dos ViewModels uno está conectado a una ventana principal y el otro está conectado a la ventana secundaria que se abre haciendo clic en un botón en la ventana principal. La ventana secundaria contiene una lista de elementos y deseo seleccionar un elemento y mostrarlo en la ventana principal actualizando el modelo de ventana principal. Cuál es la mejor manera de lograr esto. ¡Gracias!Actualizando un modelo de vista desde otro modelo de vista

+1

Ha solicitado específicamente la "mejor" forma de hacerlo. ¿Qué define "lo mejor" para ti? Podría significar el más rápido, el más simple, el más fácil de entender/depurar, el menos codificado, etc. –

+0

El más simple es muy subjetivo, pero tiendo a basarlo principalmente en el modelo conceptual de la relación real entre los objetos. Si son padres/hijos, una referencia directa podría ser muy directa. –

+1

En este contexto, "lo mejor" para mí es la forma más sencilla de hacerlo, ya que soy muy nuevo en wpf y mvvm. – codeBlue

Respuesta

10

Hay varias maneras de hacer esto.

  • pasar una referencia a la vista del modelo principal/padres en el niño y que el niño llame a la vista principal del modelo.

  • Haga que el modelo de vista secundaria desencadene un evento al que el padre se haya suscrito.

  • Utilice un mensajero/mediador para comunicarse entre los dos. El padre se suscribe, el niño publica el mensaje. Esto proporciona un acoplamiento flexible.

  • Establezca el modelo de vista principal como un servicio global. Registralo de alguna manera. Haga que el niño busque el servicio (que requiere servicios globales es un problema bastante común) y luego llame a algo en la interfaz global/común.

Desde mi experiencia, el método más simple sería # 2. Definir un evento en el modelo de vista infantil. El padre tendrá que buscar al niño (no sé si lo contiene o cómo se construyen sus modelos de vista) y suscribirse al evento.

+0

Cualquiera de estos métodos podría ser apropiado. Depende mucho del contexto. El acoplamiento no es apropiado a menos que las máquinas virtuales estén estrechamente relacionadas conceptualmente. –

+0

Respuesta muy muy útil, mi clase de MainViewModel estaba empezando a parecer un desastre absoluto. Gracias –

7

La forma estándar de comunicarse entre ViewModels es usar algún tipo de mensaje. Una buena aplicación de esto es el MVVM Light Toolkit

Aquí hay algunos (al azar) de código usando el mensajero por defecto del mismo:

//Registering: 
Messenger.Default.Register<IEnumerable<BookViewModel>>(this, true, fillSourceWith); 
Messenger.Default.Register<DisplayModeEnum>(this, ChangeMainTemplates); 
//with a specific "token" 
Messenger.Default.Register<object>(this, MessageTokens.ClearList, o => BookSource.Clear()); 

//Sending 
Messenger.Default.Send<List<BookViewModel>>(newBooks); 
Messenger.Default.Send<DisplayModeEnum>(DisplayModeEnum.MediumLayout); 
Messenger.Default.Send<object>(null, MessageTokens.ClearList); 
+0

-1. Él está hablando de la relación padre/hijo. La mensajería no es una buena idea aquí. – Euphoric

+2

Creo que la mensajería debería estar bien aquí. Sin mensajes, tendría que combinar sus modelos de vista de alguna manera. –

+0

La mensajería puede o no ser adecuada. Puede ser demasiado complicado para este problema, pero es una buena solución. –

1

La mejor manera de hacerlo es tener algún tipo de referencia de hijo a padre y actualizar este elemento principal al cerrar el elemento secundario.

O puede tener algún tipo de evento en un niño y dejar que los padres escuchen en este evento. Luego planteas este evento cuando el niño se cierra.

La mensajería se utiliza cuando ambos ViewModels no están relacionados lógicamente.

[rant] ¿La gente no sabe siquiera los principios básicos de OOP o qué? [/ Diatriba]

+1

No creo que el uso de un messenger en este caso es necesariamente un mal diseño. Dependería de cualquier cantidad de factores, pero enviar un mensaje simple podría ser mucho más simple y efectivo que establecer una relación OO entre las dos máquinas virtuales. –

+0

Creo que el problema es que no hay un método de mejores prácticas para hacerlo. como parte del patrón MVVM. – Will

1

Yo tenía el mismo problema unos días antes ;-)

Finalmente utilicé un mediador para comunicar ambas view-modelos. De hecho, utilicé el Messenger de MVVM Light.

public void Search(object parameter) 
     { 
      ChildWindow window = new ChildWindow(); 

      SearchWindow pageSearch = new SearchWindow(); 

      window.Content = pageSearch; 
      window.Show(); 

      Messenger.Default.Register<Messages.CloseWindowMessage>(this, action => this.closeWindow(action)); 
     } 

Después de eso define el mensaje con todo lo que necesitaba saber desde la ventana principal:

public class CloseWindowMessage : MessageBase 
    { 
     public bool Result { get; set; } 
     public Model.Selected Selected { get; set; } 
    } 

Finalmente el mensaje detrás de la ChildWindow es suficiente con registrar el mensaje con resultado y el objeto que quiero volver.

Debe registrarse desde el código subyacente de su vista para cerrar la ventana.

-1

Creo que la mejor manera de pasar el mensaje entre dos modelos de vista es la programación de eventos.

Cuestiones relacionadas