MVVM Передача данных в диалоговое окно Просмотр модели
Я изучаю использование MVVM, и, хотя я это понимаю по большей части, есть одна вещь, о которой я не могу опустить.
Представьте, что у меня есть комбинация View и ViewModel, которая показывает список foobars. Когда пользователь выбирает foobar в списке и нажимает кнопку редактирования, я хочу, чтобы foobar отображался во всплывающем диалоговом окне, чтобы его можно было отредактировать. Это диалоговое окно (представление) будет иметь свой собственный связанный ViewModel.
Я понимаю, что кнопка может быть привязана к команде в списке ViewModel, но отсюда как мне создать экземпляр редактора foobar?
1) Должен ли я отправить сообщение обратно в представление, которое откроет диалоговое окно? Если это так, разве это не побеждает цель иметь команду?
2) Как foobar передается в ViewModel для редактора? Если это его конструктор, не затрудняет ли объявление ViewModel в XAML?
Я чувствую, что это последний кусочек головоломки, который мешает мне использовать MVVM, и я действительно хотел бы получить прекрасное решение для развязки.
Спасибо
Matt
Ответы
Ответ 1
Я бы сделал это следующим образом:
- Команда, прикрепленная к кнопке редактирования, запускает диалог редактирования, создавая для него пользовательскую ViewModel (VM). Сама команда должна быть, возможно, либо в списке VM, либо в модели (не совсем уверен).
- Диалог редактирования Foobar VM получает ссылку на Foobar в своем конструкторе.
- foobar клонируется и клоун редактируется.
- Как только пользователь нажимает OK в диалоговом окне редактирования foobar, значения клона записываются обратно в исходный foobar в виртуальной машине (и диалог закрывается).
Потребность в клоне исходит из того, что пользователь не хочет видеть изменения в списке foobar, пока не примет изменения в диалоговом окне редактирования. Если, однако, онлайн-редактирование в порядке, клон не нужен.
Изменения распространяются автоматически.
PS: хотя я сторонник MVVM, я не уверен, что мое решение является ортодоксальным с чистой точки зрения MVVM.
Ответ 2
В этой статье из codeproject показан элемент управления WPF Dialog, который делает именно то, что вам нужно. Причина, по которой эта реализация необходима, заключается в том, что вы не можете поместить окно внутри визуального дерева любого другого элемента управления. Это означает, что из окна WPF не разрешается создавать диалог внутри окна. Поэтому в приведенной выше статье создается подкласс ContentControl, который создает окно.
В любом случае вы помещаете это в свой FooBarList View
<dialog:Dialog Content="{Binding Path=DialogViewModel}" />
Вы убедитесь, что у вас есть что-то подобное в словаре ресурсов где-то:
<Style TargetType="{x:Type dialog:Dialog}">
<Style.Triggers>
<Trigger Property="HasContent" Value="True">
<Setter Property="Showing" Value="True" />
</Trigger>
</Style.Triggers>
</Style>
и просто напишите что-нибудь вроде этого (для работы WPF вам нужно реализовать INotifyPropertyChanged):
public Class FooBarListViewModel
{
IList<FooBar> FooBarList {get;set;}
FooBar SelectedFooBar {get;set;}
ViewModelBase DialogViewModel {get;set;}
public EditFooBar(object param)
{
DialogViewModel = FooBar;
}
}
Чтобы связать View для редактирования FooBar в FooBar ViewModel, просто сделайте что-нибудь подобное (желательно в Application.Resources, чтобы оно было глобальным)
<DataTemplate DataType={x:Type vm:FooBarViewModel}>
<vw:FooBarView/>
</DataTemplate>
(Или необязательно: используйте конвертер IValueConverter для преобразования вашего представления из ViewModel как показано в этом сообщении)
И тогда вы настроены. Может показаться, что много, но это действительно освобождает вас.
Ответ 3
Отсутствует контроллер, который отвечает за рабочий процесс ViewModels. Контроллер создает ViewModels и передает необходимые данные между ViewModels.
Проект Проект WPF Application Framework (WAF) содержит примеры приложений, которые показывают, как это может работать.