2010-10-31 29 views
5

Soy algo nuevo en MVVM. No estoy seguro de cuál es la mejor manera de hacer lo que estoy tratando de hacer.Forma correcta de acceder a un modelo de vista desde un modelo de vista existente

Aquí está el panorama:

Tengo una máquina virtual que se va a mostrar otra ventana. Puedo llamar al myNewWindowView.Show(), pero primero necesito establecer algunos datos en la máquina virtual de mi nueva ventana.

¿Debo exponer tanto el myNewWindowView como el NewWindowViewModel al modelo de vista que llama?

Aquí se muestra un ejemplo:

class MainVM 
{ 
    public void FindCustomer(string nameParial) 
    { 
     List<Customer> customers = ServiceCall.GetCustomers(nameParital); 
     // This is the part I am not sure how to do. I am not sure if this 
     // View Model should have a reference to a different view model and 
     // the view too. 
     myNewWindowViewModel.CustomerList = customers; 
     myNewWindowView.Show(); 
    } 
} 

Respuesta

3

Me gustaría mantener el modelo de vista independiente de cualquier punto de vista. Tiendo a pensar en ellos como capas, pero solo son intercambiables en una dirección.

Así que un modelo de tipo foo puede tener cualquier modelo de vista superpuesto encima, y ​​nunca espera ni se preocupa por el tipo de modelo de vista.

Un modelo de vista solo puede ser para un tipo de modelo, pero no le importa ni espera qué tipo de vista lo usará.

Una vista será para un tipo particular de modelo de vista.

Lo que parece que tiene es un modelo de vista que le preocupa qué están haciendo las vistas, lo cual me parece incorrecto.

Si fuera yo, obtendría la vista para que MainVM muestre la nueva ventana, haciendo que MainVM pase el modelo de vista apropiado para la nueva ventana.

Este es el código que pondría detrás de la vista para el modelo de vista principal

class MainWindow : Window 
{ 
    public MainWindow() 
    { 
      Initialize(); 
      DataContext = new MainVM(); 
    } 

    public void FindCustomerClick(object sender, RoutedEventArgs args) 
    { 
      CustomerListView clv = new CustomerListView(); 
      clv.DataContext = (DataContext as MainVM).FindCustomer(search.Text); 
      clv.Show(); 
    } 
} 

Como se puede ver, el modelo de vista tiene un método que toma una cadena y devuelve un CustomerListViewModel, que después se aplica a la DataContext de un CustomerListView.

+0

Suena bien, pero también suena borroso. ¿Puedes mostrarme un ejemplo de cómo harías mi ejemplo, verdad? (Es decir, una ventana abre otra con algunos datos pasados ​​entre ellos.) – Vaccano

+0

Lo intentaré. Probablemente tendré que arreglarlo más tarde, ya que estoy haciendo esto desde mi teléfono :) –

+0

Esto se ve bien, excepto que mi 'CustomerListView.DataContext' se establece en mi' CustomerListViewModel'. Si configuro el resultado de 'FindCustomer' entonces pierdo la configuración de MVVM para esa vista. – Vaccano

2

No haga referencia a las vistas dentro de su modelo de vista. Haga que las vistas creen vistas y que los modelos creen modelos de vista.

Una forma simple de lograr esta separación de preocupaciones es con los eventos. La forma más rápida y sucia para hacerlo es crear una propiedad ChildViewModel en su vista del modelo de los padres y, a continuación, manejar PropertyChanged en la vista, por ejemplo:

ParentViewModel vm = (ParentViewModel)DataContext; 
vm.PropertyChanged += delegate(object sender, PropertyChangedEventArgs e) 
{ 
    if (e.PropertyName == "ChildViewModel") 
    { 
     MyChildWindow w = new MyChildWindow(); 
     w.Show(vm.ChildViewModel); 
    } 
}; 

Ahora cada vez que el modelo de vista de los padres cambia la propiedad ChildViewModel, la la vista principal abrirá una nueva vista secundaria.

A menos rápido, y menos sucio, el enfoque es crear un delegado CreateViewEventHandler y CreateViewEventArgs clase, y hacer que el controlador de eventos, y una OnCreateView método, parte de su clase base vista del modelo protegido (suponiendo que tiene uno). Esto permite que el modelo de vista sea mucho más explícito sobre cuándo se debe crear una ventana secundaria.

Tenga en cuenta que si es importante que el modelo de vista principal sepa cuándo se ha cerrado el modelo de vista secundaria, el modelo de vista secundaria puede exponer un evento al que el padre puede suscribirse (o, una vez más, usar una propiedad y el evento PropertyChanged)

Tenga en cuenta que, en ambos casos, puede escribir pruebas unitarias que verifiquen que el modelo de vista abre la ventana (es decir, plantea el evento) cuando se supone que debe implicar las vistas.

No he usado ningún framework de MVVM, pero los que he visto tienen herramientas de mensajería diseñadas para facilitar este tipo de cosas.

Cuestiones relacionadas