Довольно поздно, но я думаю, что это достаточно сложно, чтобы заслужить множество разных перспектив.
Я понимаю, что не хочу, чтобы моя виртуальная машина знала о прикрепленном View, но
Разумно ли для View иметь ссылку на свою виртуальную машину?
Как уже отвечалось, правильное расположение View-ViewModel предполагает, что ViewModel назначается в качестве свойства DataContext представления. Это позволяет автоматически связывать DataBindings из декларативного XAML или настраивать с помощью кода.
Иногда вам хочется написать в своем коде что-то вроде этого:
var dc = DataContext as CleverViewModel;
CleverViewModel.CleverProperty.Add(someValue); // just a simple example
Я полагаю, что правильный способ достичь такого рода вещей это НЕ приводить DataContext, а вместо этого:
Имеет некоторый выделенный элемент управления в View, например ItemsControl с его двусторонней базой данных ItemsSource, привязанной к некоторому свойству в viewmodel:
<ItemsSource x:Name="cleverControl" Visibility="Collapsed" ItemsSource="{Binding CleverProperty, Mode=TwoWay}"/>
Привести связанное свойство вместо всей ViewModel в коде позади:
var collection = (ObservableCollection<double>)cleverControl.ItemsSource;
collection.Add(someValue);
Обратите внимание на важное отличие: второй подход в этом примере не требует, чтобы View знал тип ViewModel, ему нужно только свойство с именем CleverProperty
типа ObservableCollection<double>
. Это позволяет мне иметь полиморфные или даже типизированные модели утки.
Если элемент управления в представлении открывает другой вид (например, диалоговое окно), я должен
справиться с этим в представлении? Кажется неправильным обращаться с ним в виртуальной машине, так как
тогда виртуальная машина имеет некоторые знания о конкретном представлении.
Это не должно происходить в строгом MVVM, и его нетрудно избежать, используя DataTemplates. DataTemplates сопоставляют данный тип DataContext с данным типом представления, поэтому каждый раз, когда изменяется datacontext ContentControl, его отображение также изменяется при условии, что у вас есть DataTemplate для этого типа:
Элемент управления в представлении может отправить команду в ViewModel, которая, в свою очередь, обновит некоторые из его собственных свойств, которые будут отражены представлением.
Представление может содержать другого представления, вне знания ViewModel. В этом случае код позади может манипулировать текстом данных содержащегося в нем представления.
Есть больше тонкостей, но я использовал этот подход с хорошими результатами. Надеюсь, это кому-нибудь поможет.