Подтвердить что ты не робот

Как создать MVVM с помощью коллекций?

У меня возникли проблемы с пониманием того, как применять шаблон MVVM при включении списков/коллекций.

Скажите, что MainModel имеет несколько свойств и методов, а также список, содержащий другие объекты DetailModel. Объекты DetailModel могут быть добавлены, удалены или переупорядочены.

В MainView будут показаны несколько элементов управления, связанных с корневой моделью, и список ListBox, заполненный из списка. Каждый элемент будет иметь свой собственный суб-просмотр через UserControl DetailModelView.

Наконец, есть MainViewModel. Это свойство обладает свойствами, поддерживаемыми свойствами и методами MainModel, связанными с Main View, с уведомлением об изменении, сохраняющим все в синхронизации. (До этого момента мне нравится шаблон - больше заявляю об этом, если есть что-то фундаментальное, чего я не хватает...)

Когда дело доходит до обработки списка, я запутываюсь. Я столкнулся с несколькими примерами, когда MainViewModel просто предоставляет список DetailModels для представления, а DetailModelViews привязаны непосредственно к моделям. Это работает, но проблематично. Он не последовательно следует шаблону (нет DetailViewModel существует), и он заставляет меня включать некоторый код, связанный с пользовательским интерфейсом, в мои детальные модели. Мне кажется ясным, что MainViewModel должен предоставить список DetailViewModels для пользовательского интерфейса для привязки, но я зациклился на том, как реализовать такую ​​вещь!

Как управлять двумя списками (DetailModels и DetailViewModels)? Я действительно смущен, когда я изначально заполняю список DetailViewModel и как я должен обрабатывать добавление, удаление или изменение порядка элементов, чтобы они синхронизировались!

4b9b3361

Ответ 1

Обычно Models - это не что иное, как объекты данных. Они не должны содержать никакого кода, чтобы делать такие вещи, как добавление/удаление элементов из списка. Это задание ViewModel's.

В вашем случае я создал бы MainViewModel, который имеет следующие свойства:

  • ObservableCollection<DetailViewModel> Details
  • ICommand AddDetailCommand
  • ICommand RemoveDetailCommand

Если ваш класс MainModel является объектом данных, вы можете либо его выставить, либо его свойства из MainViewModel. Выявление этого свойства - это подход "MVVM-пурист", при этом разоблачение всей модели иногда более практично.

Ваш MainViewModel отвечает за создание начального списка DetailViewModels, и он отвечает за добавление/удаление этих элементов. Например, в событии PropertyChanged для свойства MainViewModel.MainModel он может перестроить коллекцию MainViewModel.Details, а событие CollectionChanged для свойства MainViewModel.Details будет обновлять MainViewModel.MainModel.Details

Ответ 2

Вы имеете право иметь отдельный список DetailModels и DetailViewModels. Список DetailViewModels должен быть свойством типа ObservableCollection<DetailViewModel>. Вы можете заполнить наблюдаемый список при установке модели (или во время построения, если передать модель в конструктор вашего ViewModel.)

private ObservableCollection<DetailViewModel> m_details;
public IEnumerable<DetailViewModel> Details
{
   get { return m_details; }
}

Вы можете подписаться на m_details. CollectionChanged. Здесь вы можете обрабатывать переупорядочивание содержимого списка в Модели.

Надеюсь, это поможет.

Ответ 3

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

Как правило, главный конструктор VM будет выглядеть следующим образом:

public MasterViewModel(MasterModel m)
{
   _Model = m;
   _Detail = new ObservableCollection<DetailViewModel>(m.Detail);
}

где MasterModel.Detail - это набор объектов DetailModel, а _Detail - это поле поддержки для свойства Detail, которое отображается в представлении.

Что касается добавления, удаления и переупорядочения элементов в этом списке, в пользовательском интерфейсе, по крайней мере, это будет выполняться с помощью команд на MasterViewModel, которые должны обрабатывать как MasterModel.Detail, так и MasterViewModel.Detail. Это немного боль, но если вы не хотите повторно заполнять MasterViewModel.Detail после каждого изменения на MasterModel.Detail, это действительно неизбежно.

С другой стороны, если вы задавались вопросом "зачем мне когда-либо понадобиться писать модульные тесты для моделей просмотра?", теперь вы знаете.

Ответ 4

Вот ответ, который, я думаю, очень хорошо затрагивает эту проблему, используя ObservableViewModelCollection<TViewModel, TModel>

Это хорошо и лениво. В ctor требуется ObservableCollection и ViewModelFactory. Мне нравится, потому что он сохраняет состояние на уровне модели, где он принадлежит. Пользовательские операции в GUI могут вызывать команды на виртуальной машине, которые манипулируют M посредством общедоступных методов на M. Любые результирующие изменения на уровне M будут автоматически обрабатываться классом в этой ссылке.

fooobar.com/info/125817/...

Обратите внимание на мой комментарий относительно SL vs. WPF