2010-10-31 3 views
5

Я немного новичок в MVVM. Я не уверен, что лучший способ сделать то, что я пытаюсь сделать.Правильный способ доступа к модели просмотра из существующей модели модели

Вот сценарий:

У меня есть VM, который собирается показать еще одно окно. Я могу позвонить myNewWindowView.Show(), но сначала мне нужно установить некоторые данные в виртуальной машине моего нового окна.

Должен ли я выставлять myNewWindowView и NewWindowViewModel вызывающей ViewModel?

Вот пример:

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(); 
    } 
} 

ответ

3

Я бы держать ViewModel отдельно от любого вида. Я склонен думать о них как о слоях, но они только взаимозаменяемы в одном направлении.

Таким образом, модель типа foo может иметь любую модель обзора, расположенную поверх нее, и она никогда не ожидает и не заботится о типе вида viewmodel.

Модель просмотра может быть только для одного типа моделей, но это не волнует или ожидает, какой вид просмотра будет использовать ее.

Вид будет для определенного типа viewmodel.

То, что у вас есть, - это viewmodel, заботится о том, какие взгляды делают, что кажется мне неправильным.

Если бы это был я, я бы получил представление о том, что MainVM отобразит новое окно, получив MainVM для передачи соответствующей модели просмотра для нового окна.

Это код, который я бы поставил за видом на главную ViewModel

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(); 
    } 
} 

Как вы можете видеть, ViewModel есть метод, который принимает строку и возвращает CustomerListViewModel, который затем применяется к DataContext клиентаListView.

+0

Звучит неплохо, но также звучит нечетко. Можете ли вы показать мне пример того, как вы могли бы сделать мой пример правильно? (Т.е. есть одно окно, открывающее другое, с некоторыми данными, передаваемыми между ними.) – Vaccano

+0

Постараюсь. Мне, вероятно, придется это исправить позже, так как я делаю это со своего телефона :) –

+0

Это выглядит хорошо, за исключением того, что мой 'CustomerListView.DataContext' установлен в мой' CustomerListViewModel'. Если я настроюсь на результат «FindCustomer», я потеряю настройку MVVM для этого представления. – Vaccano

2

Не ссылайтесь на представления внутри вашей модели просмотра. Имеют представления, создающие виды, и модели представления создают модели представления.

Простым способом решения этого разделения проблем является событие. Быстрый и грязный способ сделать это, чтобы создать ChildViewModel свойство на вашей модели представления родительской, а затем обрабатывать PropertyChanged в виде, например:

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

Теперь каждый раз, когда модель Родительское представление изменяет ChildViewModel собственность, родительский вид откроет новое дочернее представление.

Менее быстрые и менее грязный подход заключается в создании CreateViewEventHandler делегата и CreateViewEventArgs класса, и сделать обработчик события, и защищенный OnCreateView метода, часть вашего базовой модели вида класса (если у вас есть). Это позволяет модели представления быть намного более явным, когда будет создано дочернее окно.

Обратите внимание, что если для модели родительского представления важно знать, когда модель дочернего представления закрыта, модель детского представления может выставить событие, которое родитель может подписаться (или, опять же, использовать свойство и событие PropertyChanged).

Обратите внимание, что в обоих случаях вы можете написать модульные тесты, которые подтверждают, что модель просмотра открывает окно (т. Е. Поднимает событие), когда предполагается, что оно не связано с представлениями.

Я не использовал какие-либо рамки MVVM самостоятельно, но те, на которые я смотрел, имеют средства обмена сообщениями, которые предназначены для облегчения такого рода вещей.

Смежные вопросы