Я не думаю, что это идеальный вариант, когда у вас есть архитектура вашего приложения, схематичная как отношения между представлениями; Я думаю, что лучший способ подумать об этом - это набор отношений между режимами просмотра, при этом взгляды висят над этим деревом по мере необходимости. Когда вы думаете об этом так, «как передаются данные» становится намного проще. Вид - это всего лишь канал между моделью просмотра и пользователем. Вы не проектируете дом как набор окон и телефонов, а затем пытаетесь выяснить план этажа. Вы начинаете с того, что делает дом и как люди будут жить в нем.
Так это легко:
Некоторые ViewModels имеют AAViewModel
свойство. В этих моделях просмотра могут быть всевозможные простые или сложные взгляды; если представление хочет, чтобы пользователь редактировал файл AAViewModel
вида viewmodel, он включает в себя AAView
, привязанный соответствующим образом к файлу viewmodel AAViewModel
. Ваши MainViewModel
и DialogViewModel
- это большие сложные интерактивные представления, которые хотят, чтобы кто-то редактировал их vm's AAViewModel
.
Если MainViewModel
является DialogViewModel
«родитель, или создан временный экземпляр DialogViewModel
просто поместить в модальный диалог, то MainViewModel
покажет диалоговое окно и посмотреть на dialogVM.AAVM.CData.IsDirty
, чтобы решить, что делать с ним. Или, возможно, он дает dialogVM.AAVM
новый экземпляр CDataClass
, прежде чем показывать диалог (возможно, клон его собственного экземпляра), и если ShowModel()
возвращает true
, то он что-то делает с dialogVM.AAVM.CData
.
Дело в том, что после того, как ваши модели будут управлять всем, для них становится относительно простым общение друг с другом. Родитель-ребенок прост: родитель дает материал ребенку и смотрит на то, что ребенок возвращает. Модель просмотра может подписаться на событие PropertyChanged
другого вида viewmodel; родительская модель просмотра может контролировать своих детей; когда что-то происходит у ребенка, родитель может решить, следует ли обновлять родного брата.В общем, дети не должны знать ничего о своих родителях; это значительно облегчает повторное использование дочерних моделей просмотра в разрозненных контекстах. Родители должны решить, что делать с этой информацией.
Все AAViewModel знает, что кто-то вручил ему копию CDataClass
; он соответственно обновляет свои публичные свойства. Тогда кто-то еще (возможно, AAView
, но он не знает) передает ему некоторые изменения, устанавливая его свойства; он соответственно обновляет свой экземпляр CDataClass
. Через некоторое время, неизвестное ему, появляется одна модель или другая модель и смотрит на это CDataClass
.
И связь между видами и режимами просмотра происходит через привязки.
UPDATE
Оказывается, что вы создаете ViewModels в своих взглядах, и в результате вы не имеете ни малейшего представления о том, как родители могут получить к ним. И теперь вы знаете, почему не так хорошо создавать модели просмотра child view.
Вот как вы вид ребенка/ViewModels в ViewModel-ориентированный дизайн я описал выше:
Во-первых, избавиться от того, что Вы делаете, чтобы создать дочерние ViewModels внутри вида.
Во-вторых, создайте DataTemplate
для детского вида модели. Это должно быть в словаре ресурсов, который объединен с ресурсами в App.xaml, но это так просто, что он не убьет вас, если вы ленитесь и просто вставьте его в Resources
двух разных видов, где он используется.
Я не знаю, как выглядят ваши объявления пространства имен. Я собираюсь предположить, что взгляды находятся в чем-то под названием xmlns:view="..."
, а viewmodels - в чем-то под названием xmlns:vm="..."
.
<DataTemplate DataType="{x:Type vm:AAAViewModel}">
<view:AAAView />
</DataTemplate>
Теперь вы можете назначить AAAViewModel
к ContentProperty
любого контроля, который наследует от ContentControl
(и это большинство из них), и шаблон будет экземпляр. Это означает, что XAML создаст для вас AAAView
и назначит этот экземпляр AAAViewModel
объекту DataContext
AAAView
, который он только что создал.
Итак, давайте создадим ребенка AAAViewModel
, а затем мы покажем его в пользовательском интерфейсе.
public class DialogViewModel
{
// You can create this in DialogViewModel's constructor if you need to
// give it parameters that won't be known until then.
private AAAViewModel _aaavm = new AAAViewModel();
public AAAViewModel AAAVM
{
get { return _aaavm; }
protected set {
_aaavm = value;
OnPropertyChanged(nameof(AAAVM));
}
}
И теперь мы можем отобразить AAAVM
в DialogView
:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ContentControl
Content="{Binding AAAVM}"
Grid.Row="0"
/>
<StackPanel Orientation="Vertical" Grid.Row="1">
<!-- Other stuff -->
</StackPanel>
</Grid>
Теперь, как MainViewModel
войти в контакт с DialogViewModel
? В случае диалогов, так как они имеют ограниченный срок службы, на самом деле не имеет большого значения позволить им создавать свои собственные режимы просмотра. Вы можете сделать это в любом случае. Я обычно склоняюсь к тому, чтобы создать его, как во втором примере ниже.
Не совсем то же самое, но близко. Во-первых, еще раз, избавитесь от того, что вы делаете, когда диалог создает свою собственную модель просмотра.
MainViewModel.cs
public CDataClass CDC { /* you know the drill */ }
public void ShowDialog()
{
var dvm = new DialogViewModel();
// Maybe this isn't what you want; I don't know what CDataClass does.
// But I'm assuming it has a copy constructor.
dvm.AAAVM.CDC = new CDataClass(this.CDC);
if (DialogView.ShowDialog(dvm).GetValueOrDefault())
{
CDC = dvm.CDC;
}
}
Обратите внимание, что следующий следующий - код вида, не viewmodel.
DialogView.xaml.cs
public static bool? ShowDialog(DialogViewModel dvm)
{
var vw = new DialogView() { DataContext = dvm };
return vw.ShowDialog();
}
Теперь вы могли позволить диалог продолжать создавать свою собственную ViewModel; в этом случае вы могли бы дать ему общественную собственность, как это:
public DialogViewModel ViewModel => (DialogViewModel)DataContext;
И метод ShowDialog так:
DialogView.xaml.cs
public static bool? ShowDialog(CDataClass cdc)
{
var dlg = new DialogView();
dlg.ViewModel.AAAVVM.CDC = cdc;
return dlg.ShowDialog();
}
И тогда родитель может взаимодействовать с это нравится вместо этого:
MainViewModel.cs
public void ShowDialog()
{
var cdcClone = new CDataClass(this.CDC);
if (DialogView.ShowDialog(cdcClone).GetValueOrDefault())
{
CDC = cdcClone;
}
}
Nice и аккуратный.
Если это диалоговое окно не является модальным, сделайте диалог viewmodel частным членом MainViewModel
и получите MainViewModel
подпишитесь на события в диалоговом режиме, чтобы быть в курсе того, что делает диалог. Всякий раз, когда пользователь обновляет копию диалогового окна CDataClass
, диалог будет поднимать DataClassUpdated
, а MainViewModel
будет иметь обработчик для этого события, который обнюхивает _dialogViewModel.AAAVM.CDC
и решает, что с ним делать. В случае необходимости мы можем привести пример кода.
Итак, теперь вы можете видеть, что я имею в виду, создавая все с точки зрения родительских/дочерних режимов просмотра и набивая их на представления, когда и когда это необходимо.
Если данные CDataClass отличаются между этими двумя представлениями, то они в основном являются отдельными экземплярами, не так ли? – Steve
http://stackoverflow.com/q/3801681/2470362 –