Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.55/76: Рейтинг темы: голосов - 76, средняя оценка - 4.55
3 / 3 / 0
Регистрация: 13.07.2020
Сообщений: 229
WPF

MVVM бизнес логика и Model

02.11.2021, 00:10. Показов 16203. Ответов 132
Метки mvvm (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет!
Я уже довольно долго пытаюсь разобраться что же представляет из себя архитектура 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) и преобразование данных. Но уверенности что я все понял как нужно, нет.
Ниже приведены примеры с которыми я сталкивался, но понятного для меня решения не нашел.

Первый пример
Пример как я это вижу:
На View есть Listbox и Button, Listbox заполняется данными из ссылки на ObservableCollection во ViewModel, которая получает их из сервиса хранящего эти данные. Button при нажатии должна очистить Listbox и заполнить его новыми данными. Model имеет ссылку на ObservableCollection из сервиса и представляет из себя только один метод который будет очищать данные в ObservableCollection и сообщать сервису о том что их надо заново сформировать и добавить в ObservableCollection.

Тоесть:
Нажатие кнопки => ViewModel вызывает в модели команду очистить список и заполнить его => Модель очищает список и просит чтоб сервис его заполнил => В ObservableCollection к которой прибинжен Listbox срабатывает уведомление об изменении коллекции и Listbox загружает новые данные из нее.

Вопрос: Нужна ли тут модель? Или ее функции может выполнить Viewmodel? Конкретно очистить список и сообщить сервису чтоб он его заполнил.


Второй пример
Второй пример:
Есть View на которой расположен Listbox в котором находятся данные о мониторах которые подключены к компьютеру. Эти данные загружает в себя сервис при запуске приложения. ViewModel имеет ссылку на данные из сервиса, View занимается их отображение в ListBox. Задача Listbox состоит не только в отображении данных, но и чтоб при двойном клике по Item в Listbox мы например отключили/включили монитор и поменяли прозрачность его иконки в Listbox.

Тоесть:
Двойной клик по Item в Listbox => ViewModel посылает в Model команду на отключение выбранного из ObservableCollection монитора => Model устанавливает для монитора флаг Activated = false и меняет прозрачность иконки монитора на Listbox (сигнализируя пользователю что монитор отключен), после этого сообщают сервису чтобы он отключил монитор.

Вопрос: Должна ли Model сообщить сервису чтоб он отключил монитор или это должна сделать ViewModel? Или тут вообще нет необходимости в Model, так как ViewModel может сама выполнить эти действия? Может быть что то из этого можно вынести в логику View?


Третий пример
Третий пример:
У нас на View есть CheckBox который при нажатии на него добавляет некоторые параметры в реестр, есть ViewModel которая при нажатии на CheckBox посылает команду в модель о том что нужно добавить параметр в реестр и проверяет успешно ли этот параметр добавился.

Тоесть:
Нажатие на CheckBox => ViewModel посылает команду о добавлении параметра, Model пытается добавить параметр в реестр и если параметр успешно добавлен то возвращает true, если доабвить не удалось то возращает false => ViewModel проверяет успешно ли добавлен параметр в реестр и устанавливает для CheckBox свойство isChecked в зависимости от полученного результата.

Вопрос: Нужно ли тут использовать Model или для этого используется сервис? Если используется Model, то что она должна в себе содержать? Логику добавления параметров в реестр? Или Model должна обращаться к сервису который будет эту логику содержать и получать от него только результат который потом передаст ViewModel?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
02.11.2021, 00:10
Ответы с готовыми решениями:

Model в MVVM
Доброго времени суток. Начал изучать MVVM и даже что-то получается сделать, но не могу сообразить, что должно быть в Model? Программа...

MVVM Model
Здравствуйте, у меня возник вопрос что должно хранится в моделе, теорию прочитал, но на практике не понимаю. Конкретно в моем вариант...

MVVM. Общение Model с ViewModel
Занимаюсь проектом WPF, первый раз пробую MVVM-паттерн. Успешно реализовал общение View и ViewModel (бинды, команды), но никак не могу...

132
3 / 3 / 0
Регистрация: 13.07.2020
Сообщений: 229
25.11.2021, 22:21  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Поудаляйте лишнее, посмотрите может ещё что-то не работает.
Цикл в RandomizerModel прерывается с ошибкой: Вызвано исключение: "System.InvalidOperationException" в System.Private.CoreLib.dll
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
25.11.2021, 23:02
xr_Sanya, сделал Фиксация e16601dc:
Фикс ошибок логики метода случайного изменения монитора.
C#
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
        /// <summary>Метод произвольно вызвает методы модели</summary>
        private async Task RandomizeAsync(MonitorModel monitorModel)
        {
 
            while (isStarted)
            {
                // TODO: цикл прерывается, в логе: Вызвано исключение: "System.InvalidOperationException" в System.Private.CoreLib.dll
                // В Модели можно добавить internal метод возвращающий все Бизнес сущности
 
                // Коллекция по которой происходит перечисление, не должна изменяться на время работы перечисления.
                // Типовой способ развязки исходной коллекции и перечисления по ней - это создание её копии.
                foreach (var monitor in monitorModel.GetMonitors().ToArray())
                {
                    Debug.WriteLine("Старая конфигурация");
                    Debug.WriteLine("-------------------");
                    Debug.WriteLine(monitor.Name);
                    Debug.WriteLine(monitor.ColorConfiguration);
                    Debug.WriteLine(monitor.IsActive);
                    Debug.WriteLine(monitor.Height);
                    Debug.WriteLine(monitor.Width);
                    Debug.WriteLine("-------------------");
 
                    // Если монитор удалён, то к нему нельзя больше обращаться.
                    if (random.Next(0, 10) > 5) // Получется удаление с вероятностью 50% - это не слишком много? Может сравнивать с 3 или 2?
                    {
                        monitorModel.DeleteMonitor(monitor.Name);
                        // Переход к следйющему циклу
                        continue;
                    }
 
                    var boolrandom = random.Next(0, 10);
 
                    if (boolrandom >= 7)
                    {
                        monitor.IsActive = true;
                    }
                    else if (boolrandom <= 3)
                    {
                        monitor.IsActive = false;
                    }
 
                    if (random.Next(0, 10) > 5)
                    {
                        monitor.ColorConfiguration = random.NextDouble();
                    }
 
                }
 
                // Добавлениме Монитора никак не связано с циклом по СУЩЕСТВУЮЩЩИМ мониторам.
                // Поэтому его стоит делать отдельным блоком.
                if (random.Next(0, 10) > 5)
                {
                    monitorModel.AddMonitor($"ServiceAdded monitor {random.NextDouble()}");
                }
 
 
                foreach (var monitor in monitorModel.GetMonitors())
                {
                    Debug.WriteLine("Новая конфигурация");
                    Debug.WriteLine("-------------------");
                    Debug.WriteLine(monitor.Name);
                    Debug.WriteLine(monitor.ColorConfiguration);
                    Debug.WriteLine(monitor.IsActive);
                    Debug.WriteLine(monitor.Height);
                    Debug.WriteLine(monitor.Width);
                    Debug.WriteLine("-------------------");
                }
 
                await Task.Delay(1000);
            }
        }
И подберите вероятности изменений.
А то GUI получается почти всегда пустой.
Первые три монитора, возможно, вообще не следует удалять.
0
3 / 3 / 0
Регистрация: 13.07.2020
Сообщений: 229
26.11.2021, 05:40  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Фикс ошибок логики метода случайного изменения монитора
Всеравно цикл ломается если потыкать на добавление мониторов.
Ну а так вроде все работает)
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
26.11.2021, 07:24
Цитата Сообщение от xr_Sanya Посмотреть сообщение
Все равно цикл ломается если потыкать на добавление мониторов.
У меня не получилось воспроизвести этот баг.
Но внёс несколько изменений Фиксация 5f84f346:
Фикс разных мелких костылей.
При синхронизации пришлось сделать слияние.
Постарался не нарушить ваши изменения, но проверьте сами.

Проблема с падением цикла возможно была из-за этого:
C#
119
120
121
122
123
124
125
126
127
128
                // Вывод это достаточно долгий метод.
                // Если в этот момент будет изменена коллекция мониторов, то цикл упадёт с исключением.
                // Поэтому лучше создавать её копию.
                // Возможно из-за это цикл иногда и падал во время добавления в момент вывода
                Debug.WriteLine("Новая конфигурация");
                foreach (var monitor in monitorModel.GetMonitors().ToArray())
                {
                    Debug.WriteLine(monitor);
                }
                Debug.WriteLine("-------------------");
Так же обратите внимание на то, что нельзя создавать асинхронные void потоки без обработки исключений в них.
Я заменил void на Task и добавил прокидывание исключения в основной поток чтобы оно не "проглатывалось".
C#
40
41
42
43
44
45
46
47
48
49
50
        protected override void OnPropertyChanged(in string propertyName, in object oldValue, in object newValue)
        {
            base.OnPropertyChanged(propertyName, oldValue, newValue);
 
            if (propertyName == nameof(RandomizerState))
            {
                if ((bool)newValue)
                {
                    // асинхронное выполнение в UI потоке, чтобы не пропадало исключение
                    Dispatcher.InvokeAsync(async () => await randomizerModel.StartAsync(monitorModel));
                }
Ещё момент, возможно не очень важный сейчас, но может в других случаях привести к проблемам.
Из-за неправильной реализации старта и остановки цикла рандомайзера, у вас может получить одновременно несколько работающих циклов.
Чтобы такого не было, надо не просто устанавливать флаг (который за время сна цикла может быть несколько раз опущен и поднят), а передавать в задачу флаг отмены.

Для флага отмены я создал маленький специальный класс:
C#
134
135
136
137
138
139
140
141
142
143
        // Класс для отмены задачи
        private class CanceledStart
        {
            public bool IsCanseled { get; private set; }
 
            public void Canseled()
            {
                IsCanseled = true;
            }
        }
При старте проверяется наличие созданного флага.
Если он уже создан (значит цикл выполняется), то старт нового цикла отменяется.
Иначе создаётся новый флаг и передаётся в новую задачу:
C#
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
        // Останавливать цикл в задаче надо неменого по иному.
        // Объект для отмены цикла запущенного в методе Start.
        private CanceledStart canceledStart;
 
        /// <summary>
        /// Запускает произвольные изменения классса настроек
        /// </summary>
        public async /* void */ Task StartAsync(IMonitorModel monitorModel)
        {
            // Предотваращение повторного старта
            if (this.canceledStart != null)
            {
                return;
            }
 
            CanceledStart canceledStart = new();
            this.canceledStart = canceledStart;
            // Определяем дружественна ли Модель
            if (monitorModel is MonitorModel model)
            {
                await Task.Run(() =>
                {
                    _ = RandomizeAsync(model, canceledStart).ConfigureAwait(false);
                });
            }
Соответственно, для остановки подымается флаг и поле очищается.
C#
47
48
49
50
51
52
53
54
        /// <summary>
        /// Останавливает произвольные изменения классса настроек
        /// </summary>
        public void Stop()
        {
            canceledStart?.Canseled();
            canceledStart = null;
        }
В самом цикле проверяется состояние флага:
C#
59
60
61
62
63
64
        /// <summary>Метод произвольно вызвает методы модели</summary>
        private static async Task RandomizeAsync(MonitorModel monitorModel, CanceledStart canceledStart)
        {
 
            while (!canceledStart.IsCanseled)
            {
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
26.11.2021, 07:26
Добавлено через 3 минуты
Цитата Сообщение от xr_Sanya Посмотреть сообщение
Ну а так вроде все работает)
Теперь подумайте над тем в чём существенно различаются обе созданные реализации.
И в каких случаях стоит использовать ту или иную.

Добавлено через 36 секунд
Как разберёмся с этим, приступим к третей реализации.
0
3 / 3 / 0
Регистрация: 13.07.2020
Сообщений: 229
27.11.2021, 04:28  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Теперь подумайте над тем в чём существенно различаются обе созданные реализации.
Теперь по сути у нас самостоятельные сущности, которые можно передавать в сервисы или другие модели, в прошлой реализации мы передавали отражения. Не нужно создавать новые объекты для отражения, тобишь оптимизация(наверное).
Также View может получать только нужные ей свойства от сущности. Сами сущности могут уведомлять об изменении внутри себя.

Цитата Сообщение от Элд Хасп Посмотреть сообщение
И в каких случаях стоит использовать ту или иную.
Первая реализация лучше подойдет когда много небольших простых объектов, а вторая это сложные объекты, мб даже с какойто логикой внутри себя.
Конкретно в случае моей программы наверное лучше использовать второй способ, так как монитор в себе несет много характеристик, пускай и без сложной логики.

Вроде все)
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
27.11.2021, 07:20
Цитата Сообщение от xr_Sanya Посмотреть сообщение
Вроде все
Есть ещё один существенный момент.
Обратите внимание на передачу данных между Model и View.
В первом случае, у нас используется передача DTO типов отражающих полностью сущности.
Изменилось одно свойство - но передаём полностью всё состояние объекта.
Во первых, это достаточно объёмно по информации. Сущности могут иметь очень большое количество свойств.
Во вторых, и VM и Модель должны иметь информацию о таких DTO, что возможно только если они части одного приложения.

Во втором случае, а нас передаётся только аргумент события состоящий из трёх свойств: имя объекта, имя свойства, значение свойства.
В такой реализации мы можем разнести Модель и VM.
Модель может быть где-то на сервере в WEB.
А VM в локальном тонком клиенте.
"Общение" между ними происходит:
- Модель сериализует аргумент события, передаёт его по сети, VM получает серию символов, десериализует аргумент события и реагирует на него;
- VM так же отправляет в Модель название нужного ей метода и значение его параметра.

Единственно, что не укладывается в эту схему это Рандомайзер.
Но он и не должен укладываться, поскольку это просто тестовая эмуляция изменений Модели.
В реальном приложении его нет и Модель измененяентся сама.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
27.11.2021, 07:28
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Как разберёмся с этим, приступим к третей реализации.
Если по этой реализации вам всё ясно - зафиксируйте её в отдельной ветке и приступим к третей реализазации.

Третья реализация - это реализация в которой Бизнес Сущности являются полноценными Моделями.
Пусть маленькие, дочерние, но Модели.

Для этого нам нужно довести их реализацию до состояния при котором мы сможем их передавать в VM.
Так как передача в VM осуществляется у нас через интерфейс, то начать надо с того, чтобы описать все нужные публично члены этих сущностей (событие и свойства) в интерфейсе в общей библиотеке.
Потом переделать интерфейс главной Модели таким образом, чтобы он сообщал только о добавлении и удалении Моделей сущностей.
0
3 / 3 / 0
Регистрация: 13.07.2020
Сообщений: 229
28.11.2021, 20:44  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Если по этой реализации вам всё ясно - зафиксируйте её в отдельной ветке и приступим к третей реализазации.
Сделано
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
28.11.2021, 21:11
Цитата Сообщение от xr_Sanya Посмотреть сообщение
Сделано
Теперь в основной ветке (master) реализуйте:
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Третья реализация - это реализация в которой Бизнес Сущности являются полноценными Моделями.
Пусть маленькие, дочерние, но Модели.

Для этого нам нужно довести их реализацию до состояния при котором мы сможем их передавать в VM.
Так как передача в VM осуществляется у нас через интерфейс, то начать надо с того, чтобы описать все нужные публично члены этих сущностей (событие и свойства) в интерфейсе в общей библиотеке.
Потом переделать интерфейс главной Модели таким образом, чтобы он сообщал только о добавлении и удалении Моделей сущностей.
0
3 / 3 / 0
Регистрация: 13.07.2020
Сообщений: 229
28.11.2021, 23:08  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Потом переделать интерфейс главной Модели таким образом, чтобы он сообщал только о добавлении и удалении Моделей сущностей.
А методы в модели нужно удалять? или только из интерфейса?
И какие аргументы должны быть в хендлере? Только enum added и removed?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
28.11.2021, 23:16
Цитата Сообщение от xr_Sanya Посмотреть сообщение
А методы в модели нужно удалять? или только из интерфейса?
Так как с Моделью работаем через интерфейс, то все методы отсутствующие в интерфейсе не будут доступны.
Если они не нужны на уровне самой Модели, то да - их лучше удалить.

Цитата Сообщение от xr_Sanya Посмотреть сообщение
И какие аргументы должны быть в хендлере? Только enum added и removed?
Да.
Больше не о чём Модель извещать не будет.
Вторым параметром аргумента события будет Модель-сущность.
Параметры её имя, свойство, значение свойства - не нужны.
0
3 / 3 / 0
Регистрация: 13.07.2020
Сообщений: 229
28.11.2021, 23:37  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Параметры её имя, свойство, значение свойства - не нужны.
Интерфейс у нас в Common, а сама domain entity лежит в model.
Аргументы ивента должны быть model и enum который описывает что с ней произошло.
Но аргументы у нас где должны лежать в model или common? Просто из Common нет доступа к domain entity.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
29.11.2021, 00:19
Цитата Сообщение от xr_Sanya Посмотреть сообщение
Интерфейс у нас в Common, а сама domain entity лежит в model.
Там сейчас должно быть два интерфейса.
Один - как и был раньше интерфейс главной Модели.
Второй - интерфейс Моделей сущностей.
Все типы, которые используюnся этими интерфейсами, тоже должны быть на их уровне (то есть в Common).
0
3 / 3 / 0
Регистрация: 13.07.2020
Сообщений: 229
29.11.2021, 05:19  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Там сейчас должно быть два интерфейса.
Один - как и был раньше интерфейс главной Модели.
Второй - интерфейс Моделей сущностей.
Все типы, которые используюnся этими интерфейсами, тоже должны быть на их уровне (то есть в Common).
Что то похожее наколдовал, что наколдовал пометил туду.
Как я понял у нас есть коллекция которая имеет ссылки на модели мониторов и это является главной моделью. Нужны уведомления только уведомления о удалении и добавлении мониторов чтобы оповещать подпищиков об изменении коллекции. Возник вопрос могут ли модели мониторов быть удалены не используя методы модели? Тоесть isDispose = true ставим и коллекция сама удаляет монитор из себя. Для этого нужна подписка на INPC каждого монитора.
Или же мы удаляем мониторы из коллекции только через методы коллекции, тогда нам нужно уведомлять об удалении/изменении только в соответствующих методах коллекции.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
29.11.2021, 11:58
Цитата Сообщение от xr_Sanya Посмотреть сообщение
Возник вопрос могут ли модели мониторов быть удалены не используя методы модели?
Это уже вопрос реализации.

Можно оставить как у нас сейчас: добавляет и удаляет только сама коллекция.

Можно сделать доступность удаления через саму Модель-сущность, но в этом случае надо чтобы коллекция подписывалась на события созданных ею сущностей и через них могла узнать когда её нужно удалить.

На мой взгляд, второй вариант достаточно специфичен (ведь добавление всё равно останется функцией только коллекции).
Возможно такая реализация где-то и пригодится, но в очень редких случаях.

Добавлено через 39 минут
Цитата Сообщение от xr_Sanya Посмотреть сообщение
Что то похожее наколдовал, что наколдовал пометил туду.
Цитата Сообщение от xr_Sanya Посмотреть сообщение
C#
6
7
8
namespace Common.Entities
{
    public class MonitorConfigurationDomainEntity : BaseInpc, IMonitorConfigurationModel
Публично работаем с Моделями только через их интерфейсы.
Поэтому этот класс должен internal быть в проекте Модели.

Цитата Сообщение от xr_Sanya Посмотреть сообщение
C#
3
4
5
    // TODO: Интерфейс модели монитора
    public interface IMonitorConfigurationModel
    {
Нам обязательно в Модели нужно событие извещающее об её изменении.
Поэтому интерфейс надо наследовать от INPC.

Так же бессмысленно включать в интерфейс string ToString();.
Этот метод объявлен в object и значит есть у любого объекта.
При желании можно добавить в интерфейс параметрический ToString(...), чтобы в зависимости от параметров получать разные строковые представления.

Цитата Сообщение от xr_Sanya Посмотреть сообщение
C#
7
8
9
10
    //TODO: Событие о изменении коллекции
    public class MonitorCollectionChangedArgs : EventArgs
    {
        public MonitorConfigurationDomainEntity Model { get; }
Соответственно, здесь должен интерфейс Модели IMonitorConfigurationModel, а не его реализация MonitorConfigurationDomainEntity.

Цитата Сообщение от xr_Sanya Посмотреть сообщение
C#
7
8
9
10
11
12
    /// <summary>Интерфейс Модели Мониторов.</summary>
    public interface IMonitorModel
    {
        // TODO: Событие о изменении коллекции(главная модель)
        event EventHandler<MonitorCollectionChangedArgs> MonitorCollectionChanged;
    }
А где методы?
Потребителям Модели нужны же возможности: добавлять, удалять, получить список Сущностей.
Изменения самих сущностей будет через методы работы с ними и их свойства.
Но то, что касается работы с коллекцией Сущностей, то это должно быть в интерфейсе Основной Модели.

Цитата Сообщение от xr_Sanya Посмотреть сообщение
C#
9
10
    //TODO: enum изменения коллекции добавляем, удаляем
    public enum MonitorEntityAction
Ок!
Но название не соответствует Правилам Именования.
Их тоже лучше соблюдать.
Можно посмотреть как в .Net называются аналогичные типы и их члены.
В данном случае лучше, например, CollectionChangedAction.
Ведь неважно для этого перечисления об уведомлении коллекции каких элементов оно уведомляет.

Цитата Сообщение от xr_Sanya Посмотреть сообщение
C#
56
57
        // TODO: Событие о удалении и доабвлении монитора
        private void OnMonitorEntityChanged(object sender, PropertyChangedEventArgs args)
C#
17
18
19
            // TODO: Покачто убрал
            public static void LoadMonitors(MonitorModel model)
            {
Ок.


Цитата Сообщение от xr_Sanya Посмотреть сообщение
C#
25
26
27
28
29
30
31
32
        // TODO: Событие о изменении коллекции(главная модель)
        // TODO: Не уверен что оно нужно ведь мы может сразу на события коллекции подписыватся?
        public event EventHandler<MonitorCollectionChangedArgs> MonitorChanged
        {
            add
            {
                if (value != null)
                {
Можно убрать - можно оставить.
Зависит от требований к реализации задачи.
Если оставить, то подписчик сразу после подписки получает через прослушку информацию о всех мониторах.
Если убрать, то подписчик после подписки должен вызвать метод Модели возвращающий все мониторы.

Цитата Сообщение от xr_Sanya Посмотреть сообщение
C#
64
65
66
67
            while (!canceledStart.IsCanseled)
            {
                // TODO: цикл прерывается, в логе: Вызвано исключение: "System.InvalidOperationException" в System.Private.CoreLib.dll
                // В Модели можно добавить internal метод возвращающий все Бизнес сущности
В Рандомайзере несколько ошибок компиляции, поэтому в это не стал вникать.
0
3 / 3 / 0
Регистрация: 13.07.2020
Сообщений: 229
30.11.2021, 04:27  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Можно оставить как у нас сейчас: добавляет и удаляет только сама коллекция.
Да, но при удалении монитор извещает об этом, теперь как я понимаю это событие не нужно?

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Зависит от требований к реализации задачи.
Если оставить, то подписчик сразу после подписки получает через прослушку информацию о всех мониторах.
Если убрать, то подписчик после подписки должен вызвать метод Модели возвращающий все мониторы.
Но мы же используем уведомление о изменении коллекции и подписчик на это событие сразу узнает что сущность удалена, или я что то не так понимаю?

Вроде как привел модели в рабочий вид, но что теперь во View должно быть?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
30.11.2021, 09:34
Цитата Сообщение от xr_Sanya Посмотреть сообщение
Да, но при удалении монитор извещает об этом, теперь как я понимаю это событие не нужно?
Оно будет дублирующим, но лучше его оставить.

Допустим, выводите просто имена всех действительных Мониторов.
Вам нужна подписка только на событие Основной Модели.
Add - добавили имя в список, Remove - удалили.
С самими мониторами вам работа не нужна.

А если убрать Remove, то придётся подписываться-отписываться ещё на событие самих Мониторов.

Цитата Сообщение от xr_Sanya Посмотреть сообщение
Но мы же используем уведомление о изменении коллекции и подписчик на это событие сразу узнает что сущность удалена, или я что то не так понимаю?
Это не относится к вопросу удаления мониторов.

Это вопрос начальной инициализации подписчика.
Вот он подписался на событие.
У него пока нет коллекции всех Мониторов.
Как ему её получить от Модели?

Он может получить её вызвав метод основной Модели или Модель сама может ему сообщить о них во время подписки.
0
3 / 3 / 0
Регистрация: 13.07.2020
Сообщений: 229
01.12.2021, 04:31  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Ок.
А что должна представлять из себя коллекция во ViewModel? Или как вообще должны работать domain entity?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,174
Записей в блоге: 2
01.12.2021, 08:28
Цитата Сообщение от xr_Sanya Посмотреть сообщение
А что должна представлять из себя коллекция во ViewModel?
В данном случае, наши domain entity это полноценные Модели, поэтому в коллекции будут они.
В этих Моделях реализован INPC, поэтому их можно напрямую передавать в View и редактировать в View.
Удаление и добавление у нас будет реализовано через события основной Модели.

Можно (в учебных целях) для перестраховки, подписаться на события и Моделей Сущностей.
И дополнительно контролировать их свойства IsAdded и IsDispose и по ним тоже удалять из коллекции и отписываться.
Но практической целесообразности в этом нет.

В View для исключения различных багов, можно коллекцию отображать не напрямую, а через фильтр отсеивая IsAdded=false или (логическое) IsDispose=true.

Добавлено через 6 минут
Если бы нам в View потребовались какие-то доп.свойства от сущностей (выделен, выбран, раскрыт и т.п.), то мы создали бы простейший контейнер в котором были эти свойства и свойство с сущностью:
C#
1
2
3
4
5
6
public class MonitorVM : BaseInpc
{
    public IMonitorConfigurationModel Monitor {get => ...; set => ....:}
    public bool IsSelected {get => ...; set => ....:}
    public bool IsExpanded {get => ...; set => ....:}
}
Добавлено через 8 минут
xr_Sanya, ещё вопрос по рандомайзеру.
Это просто тестовая эмуляция изменения данных из других источников?
В реале её быть не должно?

Если так, то не стоит его делать как "легальный" публичный интерфейс.
Это должно быть просто свойство или метод в Модели, но которые не входят в её интерфейс.

О конкретной реализации Модели может знать App.
Поэтому VM будет вызывать метод App (через обратный вызов или событие), а он включать выключать тестовый режим Модели.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
01.12.2021, 08:28

MVVM биндинг view в model
Я новичок, пытаюсь написать приложение UWP согласно паттерну MVVM В общем, в модели должен быть список экземпляров класса. В классе...

Бизнес-логика
Подскажите, как решить следующую проблему: Занимаюсь по пособию, и возникла ошибка. Код из C# public class DataCommands { ...

WPF MVVM - Transfer Data to Model
Всем привет, уважаемые. Есть два этапа: 1. Переношу коллекцию ObservableCollection из VM в Model. 2. А затем из Model в другую VM. ...

Каково назначение папки Model в MVVM
Просто я к тому, что все классы относящиеся к логике будут иметь пространство имён начинающееся с Model, это нормально вообще? Или не всю...

MVVM. Получение данных объекта по сети - в model или во viewmodel?
Здравствуйте! Вникаю в паттерн mvvm, прочитал\посмотрел кучу учебных материалов, и если честно, в голове каша уже. Мне понравился своей...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
120
Ответ Создать тему
Новые блоги и статьи
Мастера простых решений
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
Суть: рассматривается живое существо, оказавшееся внутри довольно странной системы (этого мира) и пытающееся обустроить в ней свой кусок пространства. Жизнь действительно предъявляет каждому. . .
Когда логика программы не спасает от человеческих ошибок
Maks 18.08.2026
В последнее время всё чаще и чаще сталкиваюсь с таким явлением, как абсолютная невнимательность (или глупость) пользователей. Проявляется это чаще всего на работе в коллективе. Допустим, человек с. . .
Лето уходит
kumehtar 17.08.2026
Мысли в слух
kumehtar 17.08.2026
Забавно, насколько сейчас стала доступна информация. Например о магии, духовном развитии, медитациях, и других подобных направлениях, ранее зачастую тайных, передаваемых от учителя к ученику. Хотя. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru