C# MVVM TreeView TwoWay-Binding для иерархических данных
Я гуглил ответ на этот вопрос уже более двух недель. Обычно это означает, что я либо слепой, либо идея абсурдна. В любом случае:
В довольно гибком проекте среднего размера данные конфигурации хранятся в иерархической структуре, подобной этой:
- Конфигурация (коллекция)
- Аудио (класс)
- BaseDir (структура)
- PlayMode (enum)
- Вход (класс)
- CalibrateOnConnect (bool)
- KnownDevices (коллекция)
- ... (учебный класс)
- ...
- ... (учебный класс)
- UseDevice (целое число)
- Плейлист (коллекция)
- FirstAudio (класс)
- Путь (строка)
- Повторите (целое число)
- FirstAudio (класс)
- ...
- Аудио (класс)
Мне уже удалось отобразить их в TreeView в виде шаблона MVVM. Поскольку я не могу точно сказать, какие опции будут добавлены в будущем, я использовал общий подход, создавая ViewModels для class
, ienumerable
мой обычай structs
и основные типы значений (string
, bool
, enum
...)
В моем XAML они имеют соответствующие (иерархические) шаблоны данных, например, с CheckBox для логических значений или текстовым блоком для общих типов значений.
Каждый экземпляр ViewModel имеет поле для хранения данных базовой модели.
Мне удается редактировать эти значения в View и через TwoWay-Binding также в ViewModel.
Но то, что заставляет мою голову болеть, - то, как обновить эти данные в Модели.
Поскольку я создаю иерархическую структуру ViewModel с помощью отражения, у родителей нет свойств get / set, соответствующих именам полей / индексаторам /... эквивалентного класса / коллекции конфигурации. Хотя каждый экземпляр ViewModel знает имя поля / свойства структуры данных родительской модели, из которой он был создан, и также знает его родительский экземпляр ViewModel (но не его родительский экземпляр Model).
Каждая попытка решить эту проблему с помощью команд или вызова функции обновления какого-либо родителя завязала мне мозг.
Разве нет простого способа добиться этого с помощью обычных методов привязки?
Было бы лучше, если бы я создал ViewModels для каждого класса конфигурации (под), который я использую?
Подсказка: каждый экземпляр ViewModel знает имя своего поля / свойства в структуре данных родительской модели.
1 ответ
Читая комментарии, я бы сказал, что модель представления должна быть тесно связана с моделью, которую она пытается представить. Наличие модели динамического представления также очень трудно проверить.
Однако, если вы действительно хотите попытаться обойти это, вы можете рассмотреть возможность использования Dynamic Object, который позволяет вам получать / устанавливать свойства экземпляра в совершенно общем виде. С помощью DynamicObjects вам затем предоставляются хуки, которые вызываются, когда свойство либо устанавливается, либо получает, это позволит вам (например) вызвать события NotifyPropertyChange для данного динамического свойства.