Форум программистов, компьютерный форум, киберфорум
Наши страницы
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/5: Рейтинг темы: голосов - 5, средняя оценка - 5.00
Demo_Dem
4 / 4 / 1
Регистрация: 01.09.2014
Сообщений: 54
1

MVVM Light и оповещения об изменениях модели

30.07.2015, 12:11. Просмотров 1002. Ответов 13
Метки нет (Все метки)

В общем есть модель
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
        private int _id;
        private int _contrId;
        private double _course;
        public int Id
        {
            get
            {
                return _id;
            }
            set
            {
                _id = value;
            }
        }
 
        public int ContrId
        {
            get
            {
                return _contrId;
            }
            set
            {
                _contrId = value;
            }
        }
 
        public double Course
        {
            get
            {
                return _course;
            }
            set
            {
                _course = value;
            }
        }
Во ViewModel есть коллекция этих моделей
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
        public const string InOrderHDListPropertyName = "InOrderHDList";
        private ObservableCollection<InOrderHead> _inOrderHDList;
        public ObservableCollection<InOrderHead> InOrderHDList
        {
            get
            {
                return _inOrderHDList;
            }
 
            set
            {
                if (_inOrderHDList == value)
                {
                    return;
                }
 
                _inOrderHDList = value;
                RaisePropertyChanged(InOrderHDListPropertyName);
            }
        }
Коллекция прибиндина к DataGrid. Изменения в коллекции влекут за собой изменения в DataGrid, а вот изменения в модели - нет. Но из модели можно вызвать RaisePropertyChanged только если унаследовать ее от ViewModelBase, что на мой взгляд противоречит паттерну MVVM. Можно, конечно, реализовать в моделе интерфейс INotifyPropertyChanged самостоятельно. Оно не сложно, но выглядит несколько странно, ибо где то в MVVM Light уже есть реализация. Вот собственно вопрос - как правильно оповещать интерфейс об изменениях данных в коллекции?
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
30.07.2015, 12:11
Ответы с готовыми решениями:

Messanger MVVM Light
Здравствуйте! Разбираюсь с MVVM Light. Никак не могу настроить передачу...

MVVM Light периодически отваливается
Нормально работает, компилится, а потом разе например на 10-м бабах и ...

Mvvm Light. EventToCommand не срабатывает
Всё работает. кроме этой команды, то есть вью с вью моделью связаны точно...

MVVM Light и очистка ресурсов
Собственно вопрос в том, как очистить ресурсы в MVVM Light (уничтожить...

MVVM Light генерация контролла пользователем
Здравствуйте. Стоит задача сделать так чтобы при клике на &quot;+&quot; добавлялась...

13
valera_21
368 / 353 / 93
Регистрация: 05.01.2010
Сообщений: 1,469
Завершенные тесты: 5
30.07.2015, 13:49 2
хм) https://msdn.microsoft.com/ru-ru/library/ms594710(v=vs.110).aspx выбрать TwoWay. Может и поможет
0
Demo_Dem
4 / 4 / 1
Регистрация: 01.09.2014
Сообщений: 54
30.07.2015, 13:59  [ТС] 3
Спасибо за ответ, но это оповещение модели от представления. А нужно наоборот. Походу, лучший вариант все таки самостоятельная реализация INotifyPropertyChanged
0
kenny69
burning1ife
1411 / 1233 / 292
Регистрация: 21.09.2008
Сообщений: 3,407
Записей в блоге: 9
01.08.2015, 13:14 4
Если уж следовать MVVM полностью, то по сути у вас должен быть класс InOrderHeadViewModel, который должен реализовывать INotifyPropertyChanged (в MVVM Light можно наследовать от ViewModelBase)
Из базы или сервиса получать объекты InOrderHead, преобразовывать их в InOrderHeadViewModel (можно это делать с помощью AutoMapper) и далее отображать. При сохранении изменений в базу путь обратный из InOrderHeadViewModel -> InOrderHead (можно также с помощью AutoMapper).
Все эти действия по получению и преобразованию можно вынести в репозиторий. Т.е. во ViewModel нашем мы из репозитория получаем уже готовые коллекции InOrderHeadViewModel, и отдаем обратно на сохранение такие же.
0
Demo_Dem
4 / 4 / 1
Регистрация: 01.09.2014
Сообщений: 54
01.08.2015, 13:58  [ТС] 5
kenny69, Так вот в том то и дело, что InOrderHeadViewModel есть (в топике я его назвал просто ViewModel) и он наследуется от ViewModelBase и с изменениями полей (коллекций) в этой ViewModel все отлично. Но когда меняется не коллекция, а элемент InOrderHead в коллекции (то есть по сути в Model), то изменений в View нет. Потому что Model не реализует INotifyPropertyChanged. Собственно, вопрос как раз был о правильной его реализации для Model. В библиотеке Catel, например, наряду с ViewModelBase есть класс ModelBase, от которого наследуются все Model. Но в MVVM Light ничего подобного я не нашел, поэтому не придумал ничего лучше, как создать класс ModelBase.
0
kenny69
burning1ife
1411 / 1233 / 292
Регистрация: 21.09.2008
Сообщений: 3,407
Записей в блоге: 9
01.08.2015, 14:16 6
Цитата Сообщение от Demo_Dem Посмотреть сообщение
Так вот в том то и дело, что InOrderHeadViewModel есть (в топике я его назвал просто ViewModel) и он наследуется от ViewModelBase и с изменениями полей (коллекций) в этой ViewModel все отлично.
У вас должно получится, что в во MainViewModel должна содержаться коллекция ObservableCollection<InOrderHeadViewModel>

Цитата Сообщение от Demo_Dem Посмотреть сообщение
как создать класс ModelBase.
А зачем он вообще?
По сути модель InOrderHead= набор свойств.
А InOrderHeadViewModel = свойства + INotifyPropertyChanged + валидация + ...

InOrderHead
C#
1
2
3
4
public class InOrderHead
{
    public int Id {get;set;}
}
InOrderHeadViewModel если сильно упрощенно:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
public class InOrderHeadViewModel :ViewModelBase 
{
 private int _id;
      
        public int Id
        {
            get
            {
                return _id;
            }
            set
            {
                _id = value;
               RaisePropertyChanged("Id");
            }
        }
 ...
1
Demo_Dem
4 / 4 / 1
Регистрация: 01.09.2014
Сообщений: 54
01.08.2015, 14:47  [ТС] 7
kenny69, А зачем делать плодить одинаковые модели? В Model будут свойства и такие же в ViewModel? Это не правильно. Можно просто реализовать INotifyPropertyChanged в Model (я это сделал через ModelBase).
0
Casper-SC
Эксперт .NET
3618 / 1827 / 355
Регистрация: 27.03.2010
Сообщений: 5,136
Записей в блоге: 1
01.08.2015, 14:58 8
Цитата Сообщение от kenny69 Посмотреть сообщение
преобразовывать их в InOrderHeadViewModel (можно это делать с помощью AutoMapper)
Или можно сделать обёртку и ничего не преобразовывать из обёртки давать доступ к модели, возможно, возвращая копию.

Добавлено через 43 секунды
Цитата Сообщение от Demo_Dem Посмотреть сообщение
В Model будут свойства и такие же в ViewModel? Это не правильно.
Это правильно, я тебе могу доказать где это может пригодиться. Но надо делать не копию, а обёртку.

Добавлено через 5 минут
Цитата Сообщение от Demo_Dem Посмотреть сообщение
В Model будут свойства и такие же в ViewModel?
Нужно следовать единым правилам. В одном классе обёртке это почти копия модели, в другом будут специфичные методы и свойства для индикации чего-то во вью. Если ты будешь писать то так, то сяк, в итоге получится помесь горилы с крокодилом. Следуй какому-то принципу везде. Могут быть конечно исключения, но всё же.
0
Demo_Dem
4 / 4 / 1
Регистрация: 01.09.2014
Сообщений: 54
01.08.2015, 14:59  [ТС] 9
Casper-SC, Буду благодарен, если приведете конкретный пример. А то мне что то не приходит на ум случай, когда это будет действительно необходимо.
0
Casper-SC
Эксперт .NET
3618 / 1827 / 355
Регистрация: 27.03.2010
Сообщений: 5,136
Записей в блоге: 1
01.08.2015, 15:02 10
Цитата Сообщение от Demo_Dem Посмотреть сообщение
Casper-SC, Буду благодарен, если приведете конкретный пример
Попробую. Я бы написал пример с WCF, где модель это DTO (Data Transfer Object) класс. Но я сделаю упрощение, просто сериализацию.
0
Casper-SC
Эксперт .NET
3618 / 1827 / 355
Регистрация: 27.03.2010
Сообщений: 5,136
Записей в блоге: 1
01.08.2015, 16:15 11
Лучший ответ Сообщение было отмечено Demo_Dem как решение

Решение

Вот, например, нельзя допускать ручного изменения ID из UI и вообще из вью модели. Вдруг не только ты будешь работать со своими классами и т.д. Да ещё много всего почему стоит делать так. Некоторые причины я описал выше. С ID это скорее надуманная причина, но в реальной программе могут быть другие данные важные, которые нужно защитить от дурака, то есть от того, кто не знает, что ты там задумал и что ну вот это свойство лучше руками не менять из UI и т.д. А в классе DTO свойство нельзя сделать private set, иначе как по WCF данные передавать. А обёртка запрещает менять свойство.
1
Вложения
Тип файла: rar Mvvm_ModelWrapper.rar (26.3 Кб, 29 просмотров)
Demo_Dem
4 / 4 / 1
Регистрация: 01.09.2014
Сообщений: 54
01.08.2015, 16:33  [ТС] 12
Casper-SC, Да, определенно для инкапсуляции данных это будет очень полезно. Да и пожалуй не только для этого. Например это будет удобно для того, чтобы получить нужное свойство другой модели через внешний ключ в исходной.
0
kenny69
burning1ife
1411 / 1233 / 292
Регистрация: 21.09.2008
Сообщений: 3,407
Записей в блоге: 9
02.08.2015, 18:44 13
Цитата Сообщение от Demo_Dem Посмотреть сообщение
А зачем делать плодить одинаковые модели?
А они не обязательно должны быть одинаковыми, они могут отличаться свойствами, могут быть добавлены дополнительные, убраны ненужные, у одной ViewModel может быть объединены свойства из нескольких моделей и т.д.

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

Конечно можно и напрямую с моделью работать, если нет необходимости в описанном выше... Но опять же вы спрашивали как правильнее с точки зрения MVVM.
0
Casper-SC
Эксперт .NET
3618 / 1827 / 355
Регистрация: 27.03.2010
Сообщений: 5,136
Записей в блоге: 1
02.08.2015, 18:53 14
Цитата Сообщение от kenny69 Посмотреть сообщение
Конечно можно и напрямую с моделью работать, если нет необходимости в описанном выше... Но опять же вы спрашивали как правильнее с точки зрения MVVM.
Хотел бы дополнить. Часто думается, что ничего не будет нужно, а в итоге становится нужно, так как заказчик придумывает что-то новое, так что лучше сразу делать правильно. Ну это лично моё мнение.
0
02.08.2015, 18:53
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
02.08.2015, 18:53

Доступ к свойствам из другой ViewModel [MVVM Light]
Здравствуйте! Как получить доступ к свойствам одной ViewModel из другой...

Реализация команд в wpf на mvvm light toolkit
Здравствуйте. Подскажите, пожалуйста, как можно реализовать команды в wpf на...

Правильная структура проекта C# MVVM Light с DialogService
Здравствуйте. Где нужно правильно размещать файлы относящиеся к диалогам?...


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

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru