| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > WPF и Silverlight > Обновление ListBox после десериализации |
| Автор: dAlex 13.5.2011, 10:26 | ||||||
При изменении данных в самой программе ListBox'ы обновляются нормально (добавление item'ов). А если делать десериализацию, то данные в коллекциях появляются, а в связанных с ними листбоксах нет.
описаны так
|
| Автор: jonie 13.5.2011, 11:46 |
| а как вы делаете десериализацию? При ней создается новый объект, а у вас биндинг на Cc_collection остается таким какой был наверняка.. |
| Автор: dAlex 13.5.2011, 11:55 |
| у меня создается новый объект Core, в котором все хранится. Обычные переменные десереализуются на ура и в текстбоксах появляются =) |
| Автор: dAlex 13.5.2011, 12:41 | ||
а с текстбоксами я делаю так
и все обновляется или надо после десериализации очистить листбокс и добавить туда заново все айтемы? |
| Автор: Brilona 13.5.2011, 14:28 |
| Я могу ошибаться, но думаю, что нужно использовать NotifyCollectionChanged вместо NotifyPropertyChanged. |
| Автор: dAlex 13.5.2011, 14:38 | ||
пробую =) делаю по аналогии с propertyChanged
|
| Автор: Kefir 13.5.2011, 15:27 |
| dAlex, коллекция, к которой привязываются листбоксы должна реализовывать INotifyCollectionChanged (например ObservableCollection). |
| Автор: Brilona 13.5.2011, 16:42 | ||
|
| Автор: dAlex 16.5.2011, 09:17 | ||
Всё равно, изначальная коллекция также обновляется, как и было, а свойства - нет
Core._Cc_collection обновляется, Cc_collection остается пустым |
| Автор: -Mikle- 16.5.2011, 10:04 |
| После десериализации вызовите событие PropertyChanged для свойства "Cc_collection". CollectionChanged используется, если меняется коллекция в существующем экземпляре коллекции. |
| Автор: -Mikle- 16.5.2011, 12:38 |
| Нет. Это, например, вы десериализовали (или создали) коллекцию. Затем, при нажатии на кнопку (или еще как-нить) вызываете метод Add (AddRange, Insert, Clear, Remove и т.д.) у коллекции. То есть это когда меняется существующая (уже забинденная) коллекция. Другое дело, если в какой-то момент создается новая коллекция (new) и затем присваивается свойству. В этом случае оповещение должно происходить об изменении свойства (в вашем случае Cc_collection), так как с логической точки зрения коллекция не изменялась (изменилось свойство, которое будет ссылаться на новый экземпляр). Еще одно важное замечание: любое событие должно вызываться от имени самого объекта, а не от чужого. Биндинги следят за этим и если экземпляр не тот, то игнорируют любое событие об изменении (CollectionChanged, PropertyChanged и т.д.). В заключении, предлагаю вам новое решение: 1) Уберите все свойства типа Cc_collection (которые просто делегируют значения свойству Core). 2) Оставьте (или объявите, если еще у вас нет) только свойство Core (открытое). Если я правильно понял, то именно ему вы присваиваете результат десериализации, то есть оно у вас рутовое (если нет, поправьте). 3) В его сетере пропишите вызов события PropertyChanged - OnPropertyChanged("Core") 4) Во всех диндингах, вместо, например, ItemsSource="{Binding Cc_collection}" пишите ItemsSource="{Binding Path=Core.Cc_collection}" Что получилось теперь, после того как вы десериализуете ваш рутовый объект и присвоите его свойству Core, то автоматически вызовется событие PropertyChanged (пункт 3) и все биндинги обновятся, так как в путях биндингов будет присутствовать часть Core. |
| Автор: dAlex 16.5.2011, 13:22 | ||
Сделала свойство Core, забиндила на него, прописала ему OnPropertyChanged, но все равно после десериализации пустота. Наверное, дело в
а как вызвать OnPropertyChanged от имени самого объекта? И еще - обычные переменные в текстбоксах появляются, почему? |
| Автор: -Mikle- 16.5.2011, 14:06 | ||||||
| Ох... не видя кода и имея только общее представление о том что у вас, трудно даже пример привести... Ну ок... Имеем наш объект:
Имеем виндоу:
И имеем код бехинд такой к нему:
Тут все работает как надо. Свертесь со своим кодом по этому примеру. Надеюсь, что это поможет. |
| Автор: dAlex 16.5.2011, 14:35 | ||||||
| хм, то есть я зря свойства все перенесла в MyRootData, надо будет исправить... Сделала как вы сказали, наконец-то свойство Cc_collection обновляется =) но листбокс на форме почему-то все равно пустует
|
| Автор: -Mikle- 16.5.2011, 17:13 | ||
Вообще дублирование без необходимости это всегда зря.
Вот отсюда остальные проблемы. Я так понимаю у вас было поле класса с именем Core, которое использовалось везде. Значит делаете так: 1) поле класса переименовываете в _core (без рефакторинга) 2) Свойство pCore -> Core. Теперь, везде где использовалось поле Core, будет использоваться свойство Core и все будет в порядке с вашим кодом. Вообще старайтесь избегать обращения к полям (которые хранят значения свойств) даже изнутри класса. Лучше использовать обращение к свойствам, компиляторы уже умеют оптимизировать подобные вызовы. |
| Автор: dAlex 16.5.2011, 21:15 |
| нет-нет, не так было =) изначально у меня не было поля Core, был объект Core, который использовался, и в классе окна были определены свойства полей Core, которые раньше в самом Core и находились. А когда возникла необходимость создать поле, его я назвала pCore, чтобы проверить гипотезу. Потом, как заработает, я все переименую (там просто многовато, а остальные методы нужны рабочими) |
| Автор: -Mikle- 16.5.2011, 23:54 |
| Я ничего не понял, но обратите внимание, что если у вас pCore, то вы должны использовать именно его (свойство pCore, а не поле Core) во всех биндингах и в методе Load. Это важный момент, я думаю вы понимаете. |
| Автор: dAlex 17.5.2011, 09:47 |
| Так. В общем, переделаю все по-нормальному, перенесу обратно свойства, сделаю как вы сказали и попробую снова =) |
| Автор: -Mikle- 17.5.2011, 09:54 |
Надеюсь вы правильно поняли, потому что эта фраза заставила меня засомневаться. |
| Автор: dAlex 17.5.2011, 10:37 | ||||
| переделала, все красиво и работает =) кстати нашла ошибку в своем предыдущем коде, она ужасна
еще бы там пусто было =)
да, все, как в вашем примере =) |
| Автор: -Mikle- 17.5.2011, 10:41 |
| Рад, что у вас все получилось |