Правильный способ доступа к модели представления из существующей модели представления - PullRequest
5 голосов
/ 31 октября 2010

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

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

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

Должен ли я выставить и myNewWindowView, и NewWindowViewModel для вызывающей модели представления?

Вот пример:

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

Ответы [ 2 ]

3 голосов
/ 31 октября 2010

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

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

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

Представление будет для определенного типа модели представления.

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

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

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

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 CustomerListView.

2 голосов
/ 31 октября 2010

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

Простой способ осуществить это разделение интересов - это события. Быстрый и грязный способ сделать это - создать свойство 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, но у тех, на которые я смотрел, есть инструменты обмена сообщениями, предназначенные для облегчения такого рода вещей.

...