MVVM Посмотреть ссылку на ViewModel - PullRequest
12 голосов
/ 29 марта 2010

Я использую MVVM в приложении WPF. Я очень новичок в обоих. Позвольте мне заявить, что я не являюсь самым чистым в шаблоне MVVM, я пытаюсь использовать как можно больше лучших практик, но пытаюсь найти то, что я считаю разумными компромиссами, чтобы он работал в нашей среде. Например, я не пытаюсь достичь 0% кода в моем коде View.

У меня есть пара вопросов о лучших практиках.

1) Я понимаю, что не хочу, чтобы моя виртуальная машина знала о присоединенном представлении, но разумно ли для представления иметь ссылку на свою виртуальную машину?

2) Если элемент управления в представлении открывает другое представление (например, диалоговое окно), следует ли мне обрабатывать это в представлении? Кажется неправильным обращаться с ним в ВМ, так как с тех пор у ВМ есть знания о конкретном Представлении.

Ответы [ 5 ]

13 голосов
/ 31 марта 2010

1) Вид определенно ссылается на ViewModel через DataContext. И вам разрешено использовать DataContext в вашем представлении:

public class ShellView : Window 
{
   …
   public ShellViewModel { get { return DataContext as ShellViewModel; } }

Это не является нарушением паттерна Model-View-ViewModel.

.

2) Вы правы. ViewModel не должен открывать другой вид. Лучшим подходом является использование контроллеров. Они несут ответственность за рабочий процесс приложения.

Если вас интересует более подробная информация, вы можете ознакомиться с WPF Application Framework (WAF) .

3 голосов
/ 30 марта 2010

1) Вот две простые практики для «знания о» ViewModel в View. Разумно, чтобы View знал о ViewModel (для привязки данных), но он может вам не понадобиться в вашем случае. Посмотрите, поможет ли один из этих подходов решить вашу проблему. Есть и другие способы, но они должны быть достаточно простыми:

public View(ViewModel vm)
{
     View.DataContext = vm;
}

public Bootstrapper(View v, ViewModel vm)
{
     v.DataContext = vm;
     //or, if you want it to have no parameters
     View v = new View();
     ViewModel vm = new ViewModel();
     v.DataContext = vm;
}

Первый вариант неплох, если у вас есть инструмент определения местоположения службы, но есть разновидность MVVM, которой не нравится какой-либо код в View-Behind вида. Второй вариант тоже неплох, должен быть достаточно простым для вашей задачи.

2.) Этот вопрос может быть немного неприятным моментом в дизайне MVVM. Если мы говорим об общем Win32 MessageBox, я часто разделяю эту логику на дополнительный объект и помещаю ее в виртуальную машину. Этот способ имеет тенденцию быть немного более понятным. (Например, я выбрал элемент в ListBox, к этому действию я прикрепил Delete ICommand, и в моем ViewModel, когда эта ICommand выполнена, я вставлю свой MessageBoxObject, чтобы спросить, «хочет ли пользователь действительно удалить вещь). Более продвинутые «Диалоги» будут использовать дополнительные ViewModels и DataTemplates для этих ViewModels. Я предпочитаю подход Mediator .

2 голосов
/ 10 октября 2014

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


Я понимаю, что не хочу, чтобы моя виртуальная машина знала о прикрепленном View, но Разумно ли для View иметь ссылку на свою виртуальную машину?

Как уже отвечалось, правильное расположение View-ViewModel предполагает, что ViewModel назначается в качестве свойства DataContext представления. Это позволяет автоматически связывать DataBindings из декларативного XAML или настраивать с помощью кода.

Иногда вам хочется написать в своем коде что-то вроде этого:

var dc = DataContext as CleverViewModel;
CleverViewModel.CleverProperty.Add(someValue); // just a simple example

Я полагаю, что правильный способ достичь такого рода вещей это НЕ приводить DataContext, а вместо этого:

  1. Имеет некоторый выделенный элемент управления в View, например ItemsControl с его двусторонней базой данных ItemsSource, привязанной к некоторому свойству в viewmodel:

    <ItemsSource x:Name="cleverControl" Visibility="Collapsed" ItemsSource="{Binding CleverProperty, Mode=TwoWay}"/>

  2. Привести связанное свойство вместо всей ViewModel в коде позади:

    var collection = (ObservableCollection<double>)cleverControl.ItemsSource; collection.Add(someValue);

Обратите внимание на важное отличие: второй подход в этом примере не требует, чтобы View знал тип ViewModel, ему нужно только свойство с именем CleverProperty типа ObservableCollection<double>. Это позволяет мне иметь полиморфные или даже типизированные модели утки.


Если элемент управления в представлении открывает другой вид (например, диалоговое окно), я должен справиться с этим в представлении? Кажется неправильным обращаться с ним в виртуальной машине, так как тогда виртуальная машина имеет некоторые знания о конкретном представлении.

Это не должно происходить в строгом MVVM, и его нетрудно избежать, используя DataTemplates. DataTemplates сопоставляют данный тип DataContext с данным типом представления, поэтому каждый раз, когда изменяется datacontext ContentControl, его отображение также изменяется при условии, что у вас есть DataTemplate для этого типа:

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

  2. Представление может содержать другого представления, вне знания ViewModel. В этом случае код позади может манипулировать текстом данных содержащегося в нем представления.

Есть больше тонкостей, но я использовал этот подход с хорошими результатами. Надеюсь, это кому-нибудь поможет.

2 голосов
/ 29 марта 2010

1). Представлению понадобится ссылка на модель представления на некотором уровне, поскольку модель представления будет действовать как текстовый вид представления.

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

Вы можете использовать команду для создания нового экземпляра диалоговой модели представления, которая будет иметь соответствующую таблицу данных, определенную в ваших ресурсах. Этот шаблон будет установлен для привязки к типу dialogviewmodel.

1 голос
/ 01 апреля 2010

Создайте свой собственный MVVM Framework

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

Ключевые моменты:

  1. Соглашение по конфигурации
  2. Сначала ViewModel

Что очень похоже на философию ASP.NET MVC.

Я настоятельно рекомендую посмотреть видео.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...