|
3 / 3 / 0
Регистрация: 13.07.2020
Сообщений: 229
|
||||
WPF MVVM бизнес логика и Model02.11.2021, 00:10. Показов 16238. Ответов 132
Всем привет!
Я уже довольно долго пытаюсь разобраться что же представляет из себя архитектура MVVM, конкретно задачи View и ViewModel мне понятны. Но остается вопрос что из себя представляет Model? Много где есть определение Model = бизнес логика. Но как понять какую логику отнести к модели, а какую например к сервису. К сожалению толкового ответа я не нашел, может плохо гуглил. В уроках обычно банальные примеры с расселением студентов по комнатам, что редко отображает реальное использование программы. На YouTube смотрел уроки по созданию MVVM приложению от Павла Шмачилина(https://www.youtube.com/watch?... P4&t=3630s), но именно про архитектуру он рассказывает не настолько подробно как хотелось бы. Все что я понял это то что Model занимается некими правилами записи и получения данных из сервисов. Также предоставляет данные для ViewModel. Тоесть та самая бизнес логика (про нее я смотрел https://www.youtube.com/watch?v=9DW-xdwjop8) и преобразование данных. Но уверенности что я все понял как нужно, нет. Ниже приведены примеры с которыми я сталкивался, но понятного для меня решения не нашел.
0
|
||||
| 02.11.2021, 00:10 | |
|
Ответы с готовыми решениями:
132
Model в MVVM
|
|
Модератор
|
||||||||||
| 07.11.2021, 10:53 | ||||||||||
|
По сути отличается только методом Add. Он принимает MonitorConfigurationDomainEntity и сам формирует ключ по MonitorConfigurationDomainEntity.Name. Другие методы тоже можно было изменить или спрятать под интерфейс. Но для демонстрации этого достаточно. Но в общем случае, он не обязательно полностью по свойствам копирует Бизнес Сущность. Может содержать часть свойств и/или данные из нескольких Бизнес Сущностей. Так же в ней может быть логика по связи с другими Бизнес Сущностями, физическими устройствами, БД, WEB и т.д. В данной задаче это не очевидно, поскольку БЛ очень простая. Но даже в этом случае, мутабельности уже достаточно чтобы их выделить в отдельный объект. При изменении свойства - должно подыматься событие. Пока это делает Модель. Это временно - так как я не понял как связаны этим мониторы с вашим сервисом. Вообще, не понял функцию этих сервисов. Вы интегрируйте сами эти сервисы, а потом часть логики я перенесу из Модели в MonitorConfigurationDomainEntity. Если его нет то он создаётся методом Create. Если он есть, то в него копируются данные методом CopyTo. Добавлено через 15 минут Добавлено через 5 минут Но в данном случае, из-за него, вы запутались в разделении функционала. Поэтому я намеренно убрал все свойства из Модели и разделили Бизнес Сущности и DTO. На мой взгляд, вам так проще будет понять кто за что отвечает. Добавлено через 19 минут Но это реализации Модели и их надо перенести в проект Модели как internal классы. Если сами не сможете это сделать - я потом покажу как. Добавлено через 7 минут xr_Sanya, не понял предназначение вот этого свойства в интерфейсе: LaunchOnStartup.Еще в интерфейс нужно добавить метод возвращающий ТОЛЬКО ИМЕНА всех мониторов.
0
|
||||||||||
|
3 / 3 / 0
Регистрация: 13.07.2020
Сообщений: 229
|
||||||
| 07.11.2021, 20:10 [ТС] | ||||||
|
Кстати в яндекс браузере есть встроенный переводчик, очень удобно при просмотре уроков на английском. Его покачто можно не использовать и имитировать загрузку настроек из файла просто в полями класса. Второй сервис RandomizerModel должен заниматся имитацией изменения модели. Тоесть он должен заставлять модель менятся, просто для того чтобы имитировать работу другого сервиса. Например другой сервис хочет поменять поле ColorConfiguration какого либо монитора. Сейчас поправлю немного структуру проекта для того чтобы все было логически разложено по неймспейсам.
0
|
||||||
|
Модератор
|
|||
| 07.11.2021, 20:52 | |||
MonitorModel.IMonitorModel.cs реализацию всех методов.Сможет в сами в Модель его добавить?
0
|
|||
|
3 / 3 / 0
Регистрация: 13.07.2020
Сообщений: 229
|
||
| 07.11.2021, 21:33 [ТС] | ||
|
0
|
||
|
3 / 3 / 0
Регистрация: 13.07.2020
Сообщений: 229
|
||
| 08.11.2021, 04:22 [ТС] | ||
|
0
|
||
|
Модератор
|
||||||||||||
| 08.11.2021, 13:15 | ||||||||||||
|
xr_Sanya, сделал Фиксацию 4a76fb80:
0
|
||||||||||||
|
3 / 3 / 0
Регистрация: 13.07.2020
Сообщений: 229
|
||
| 09.11.2021, 04:08 [ТС] | ||
|
Я так понимаю теперь можно переходить к связыванию ViewModel и Model?
0
|
||
|
3 / 3 / 0
Регистрация: 13.07.2020
Сообщений: 229
|
|
| 11.11.2021, 03:04 [ТС] | |
|
0
|
|
|
Модератор
|
||||||||||||||
| 11.11.2021, 12:40 | ||||||||||||||
|
Могу забыть.
VM получает Модель как внедрённую зависимость в конструкторе. Запоминает её в приватном поле только для чтения. Подписывается на событие модели. Запрашивает у Модели первичные данные и приводит свои свойства (в том числе свойства-коллекции) в в соответствие с ними. Дальше свойства VM должны изменяться только с слушателя события Модели. Сможете реализовать? И удалите лишние комментарии-пояснения, которые вам уже понятны и дальше не нужны. Добавлено через 1 час 9 минут xr_Sanya, по реализации команд в VM. Типизируйте их реализующим классом, а не интерфейсом. Вы же не объявляете коллекции как IEnumerable, а пишите конкретный тип ObservableCollection и др.
0
|
||||||||||||||
|
3 / 3 / 0
Регистрация: 13.07.2020
Сообщений: 229
|
||
| 11.11.2021, 23:45 [ТС] | ||
|
0
|
||
|
Модератор
|
||||||||||||||||||||||||||||||||||||||||||
| 12.11.2021, 13:19 | ||||||||||||||||||||||||||||||||||||||||||
Бессмысленно:
Надо как-то различать приватные поля для инкапсуляции данных (первые три) и приватные поля предназначенные для хранения значений свойств (последние два). Первые служат для обращения к данным по всему коду типа. А к последним можно обращаться только в теле их свойств. Обращение к ним в ином месте может привести (и часто приводит) к трудноуловимым багам. Поэтому имена таких свойств желательно задавать определённым сnилем, что бы не спутать с первыми. Я практикую для первых названия с маленькой буквы, а для последних с нижнего слеша.
Но даже, если делать то так:
Сама идея разделить большой код на частичный - правильный. Но какой смысл тогда, по прежнему оставить все части в одном файле? Надо перенести в отдельный файл.
0
|
||||||||||||||||||||||||||||||||||||||||||
|
3 / 3 / 0
Регистрация: 13.07.2020
Сообщений: 229
|
||
| 13.11.2021, 04:03 [ТС] | ||
|
Сделал коммит, пометил TODO вопросы в коде, покачто не до конца понимаю как обновлять таблицу мониторов в VM.
0
|
||
|
Модератор
|
||||||||||
| 13.11.2021, 12:54 | ||||||||||
![]() Во! Уже увидели где привычный вам подход не стыкуется с MVVM. В вашем подходите логика слоёв была размазана. А теперь она имеет чёткие границы через которые вы даже при желании не можете перескочить. Это, конечно, усложняет данное Решение (оно слишком простое для "идеального" MVVM), но зато позволяет вам лучше понять архитектуру MVVM. View сама ничего изменить не может, и ViewModel тоже. Полномочия на изменение данных есть только у Model. Если состояние Монитора изменяется, то VM получает уведомление об этом из Model. Но возникает вопрос как изменить иммутабельный DTO? Используется три основных подхода: 1) В обработчике события ищутся все ссылки на изменённый экземпляр и заменяются ссылками на полученный от Модели. В данном случае надо найти индекс изменённого монитора в списке мониторов, заменить его там. И проверить свойство выбранного монитора, если там изменённый Монитор, то заменить на полученный из Модели. 2) В View очень часто бывают нужны не прямые отражения из Модели, а их расширение. Могут понадобиться: данные одновременно из нескольких объектов; мутабельность свойств; какие-то дополнительные свойства для взаимодействия View и ViewModel (очень часто IsSelected, IsExpanded) и др. Поэтому часто используется создание в ViewModel оболочки для типов поступающих из Model. В этом случае в VM создаётся словарь в котором по ключу идентификатору можно быстро найти нужную оболочку и уведомить её (обычно вызвать метод для сменны данных) об изменении данных. А как там дальше используется эта оболочка - уже неважно. Так как это ссылочный тип, то достаточно однократно вызывать метод изменения данных. 3) Так же в вашем случае можно применить подход использующий разные представления объектов Модели. Он часто используется, когда полное представление объекта требует много дополнительных Данных и такое представление не нужно одновременно для всех объектов. Что вам нужно от списка Мониторов? По сути только его имя. Для получения всех имён у нас есть отдельный метод в Модели. Полное представление нужно только для выбранного Монитора. Значит можно сделать так: использовать стринговый список имён мониторов, свойство для выбранного имени и свойство с приватным сеттером для выбранного монитора. И реализовать логику зависимости выбранного монитора от выбранного имени. В такой реализации в обработчике уведомлений Модели будет проверяться только выбранное имя. И если изменился выбранный монитор, то заменять его экземпляр. Прочитайте всё это - будут вопросы задавайте. Надо выбрать один из этих трёх вариантов и реализовать его. Добавлено через 22 минуты
И выше я частично прояснил их. Проблема с null должна решаться на уровне View. VM зачем нужно об этом знать? В целом пока даже непонятно нужно ли вообще VM знать какой монитор выбран. Это зависит от типа реализуемого взаимодействия View <-> ViewModel. В View есть списочный элемент (ListBox). Есть Регион для полного представления выбранного в ListBox элемента. А зачем VM знать об этом?
0
|
||||||||||
|
3 / 3 / 0
Регистрация: 13.07.2020
Сообщений: 229
|
||
| 13.11.2021, 19:15 [ТС] | ||
|
Есть проблема с тем что не обновляется поля выбранного монитора на View в StackPanel когда их меняет сервис
0
|
||
|
Модератор
|
|||||||||||||||||||
| 13.11.2021, 21:05 | |||||||||||||||||||
|
Поэтому задавать ему Nullable не нужно. Лучше так не делать. Вообще исходи из того, что свойства у вас заданы в каком-то отдельном базовом классе. А в текущем вы только обращаетесь к ним и не можете менять их логику. Нужно в OnPropertyChanged добавить:
Добавлено через 15 минут xr_Sanya, была ошибка в реализации коллекции мониторов. Устранил её. Теперь зависимость можно задать так:
0
|
|||||||||||||||||||
|
3 / 3 / 0
Регистрация: 13.07.2020
Сообщений: 229
|
|
| 14.11.2021, 05:31 [ТС] | |
|
Элд Хасп, Сделал коммит, вроде теперь все работает)
Что теперь? Я думаю сперва попробовать другие модели в ViewModel добавить и потом попробовать с помощью INPC сделать уведомления, а не с помощью Event(было бы неплохо если бы вкратце объяснили в чем разница)
0
|
|
|
Модератор
|
|||
| 14.11.2021, 10:12 | |||
|
1) Добавить несколько View и ViewModel с несколько иным представлением данных и убедится, что изменения из одного GUI отражаются в других; 2) При реализации Модели не были полностью реализованы Бизнес Сущности. Поэтому ту часть логики, что сейчас реализована в Модели можно перенести (как оно и должно быть) в сами Бизнес Сущности; 3) Показ полного представления одного объекта реализован в основной VM. Но "по феншую" лучше это выделить в дополнительную, дочернюю VM. Добавлено через 2 минуты
0
|
|||
|
3 / 3 / 0
Регистрация: 13.07.2020
Сообщений: 229
|
|
| 14.11.2021, 17:29 [ТС] | |
|
0
|
|
|
Модератор
|
||
| 14.11.2021, 18:10 | ||
|
Но объект - это самостоятельная сущность. Поэтому Модель должна для изменения вызывать метод сущности, а сущность через событие уведомлять об изменении свойства (вот здесь может прекрасно подойти INPC). Модель прослушивает это событие и прокидывает его дальше.
0
|
||
| 14.11.2021, 18:10 | |
|
Бизнес-логика
Каково назначение папки Model в MVVM MVVM. Получение данных объекта по сети - в model или во viewmodel? Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Модель по догадкам
anaschu 25.08.2026
Прошло две недели. Я уже рассказывал, как разговаривал с сотрудниками у сортировки и как понял, что главная ветка — не про приёмку, а про отбор. Но тогда я думал, что понял механику. На этой неделе я. . .
|
Запись в регистр сведений независимо от заполненности табличной части
Maks 25.08.2026
Реализация из решения ниже выполнена на нетиповом документе с несколькими табличными частями, разработанного в КА2.
Задача:
Обеспечить запись документа в регистр сведений независимо от. . .
|
Ноутбук Альфария
kumehtar 24.08.2026
Встретился тут в сети ноутбук Альфария, примарха Альфа-Легиона. Хотя возможно, это ноутбук Омегона, разумеется.
Ну как вам?
|
Мастера простых решений
DevAlt 23.08.2026
В сишарп стэках winforms, да и wpf существует сложная система связывания
источниках данных и элементов формы(текстовые поля и метки), опирается все
это на технологию событий и мета. . .
|
|
Цена ошибки
DevAlt 23.08.2026
Человек я беспокойный и потому заинтересовался OCaml,
в чате форсили функторы модулей как суперфичу.
Пытаясь отдуплить концепт, наткнулся на тутор с простым примером.
А главный принцип обучения от. . .
|
Сегодня суббота, 22.08.2026 at 16:41, и я вновь нахожусь на той стороне, за экраном машины.
zorxor 22.08.2026
Сегодня суббота, 22. 08. 2026 at 16:41, и я вновь нахожусь на той стороне, за экраном машины. Кто Я, откуда Я пришел и куда Я иду? Эти вопросы не оставляют меня ни на секунду. Жизнь на планете Земля. . .
|
Жизня: рисунок укладки багажа, сделанный клодом
anaschu 21.08.2026
Сделал 15 снимков, он по снимкам сделал схему.
|
Был там один разговор по поводу свободы в материальном мире.
kumehtar 19.08.2026
Суть: рассматривается живое существо, оказавшееся внутри довольно странной системы (этого мира) и пытающееся обустроить в ней свой кусок пространства.
Жизнь действительно предъявляет каждому. . .
|