Получение данных из изолированного хранилища в модель представления

У меня серьезный психический блок, и мне нужна помощь. Я использую приложение с привязкой к данным для Windows Phone в качестве отправной точки моего проекта и вполне доволен тем, как взаимодействуют модель, модель представления и представление.

Моя проблема заключается в том, что данные, используемые в примере, создаются во время выполнения и добавляются в объект ObservableCollection. Насколько я понимаю, создание новых объектов ItemViewModel и последующее добавление их в ObservableCollection запускает эквивалент событий NotifyPropertyChanged, которые гарантируют, что все привязки в представлении обновляются. Если мое объяснение неверно, буду рад любым мыслям.

Теперь генерация данных во время выполнения бесполезна в большинстве реальных примеров, и поэтому мне нужно сериализовать данные в изолированное хранилище. Это я сделал и могу успешно сохранить и загрузить свой объект ObservableCollection.

Моя проблема возникает, когда я загружаю данные из IsolatedStorage, а затем назначаю возвращенную ObservableCollection объекту Items в модели представления.

    public void LoadData()
    {
        App.Measurements = Serialization.Read<measurements>(App.MEASUREMENTS);
        this.IsDataLoaded = true;
    }

App.MEASUREMENTS просто в глобальной переменной, содержащей имя файла, который будет использоваться в IsolatedStorage.

Приведенный выше код извлекает данные и присваивает их Items ObservableCollection, но пользовательский интерфейс не обновляется. Если я заменю приведенный выше код на:

    public void LoadData()
    {
        foreach (measurement m in App.Measurements.WeightMeasurements)
        {
            this.Items.Add(m);
        }
        this.IsDataLoaded = true;
    }

и перебрать полученную коллекцию и добавить новую коллекцию ItemViewModel в коллекцию Items, после чего все правильно обновится в пользовательском интерфейсе.

Мой xaml имеет правильные привязки, и DataContext также установлен правильно.

Я пробовал множество способов, пытаясь решить эту проблему, но я не могу поверить, что единственный способ - перебрать всю загруженную коллекцию, добавив ее в коллекции Items, только некоторые события сработают!

Приветствуются любые мысли.

Джейсон.


person Jason James    schedule 05.07.2011    source источник


Ответы (2)


Вы реализуете INotifyPropertyChanged на Items?

В качестве ObservableCollection он будет обрабатывать вызов INPC для отдельных элементов в коллекции, когда они изменяются, но вам все равно нужно обрабатывать это для самого свойства.

person Matt Lacey    schedule 05.07.2011
comment
Я реализовал INotifyPropertyChanged в классе Items, но проблема заключается в том, что ObservableCollection‹Items› не запускает событие CollectionChanged, когда десериализованная коллекция назначается коллекции Items. - person Jason James; 05.07.2011
comment
@ Джейсон, можете ли вы предоставить репро-проект, чтобы подтвердить это? - person Matt Lacey; 05.07.2011
comment
я могу отправить его вам напрямую? Не очень хочется, чтобы это выкладывали сюда! Могу ли я использовать ваш адрес электронной почты с вашего сайта? - person Jason James; 05.07.2011
comment
подскажите пожалуйста куда отправить. Спасибо, Джейсон. - person Jason James; 05.07.2011
comment
Создайте проект, максимально воссоздающий вашу проблему, и разместите здесь ссылку. Я не могу обещать что-либо сделать с тем, что вы пришлете мне по электронной почте. Размещение его здесь означает, что другие могут дать ответы или извлечь выгоду из решения, когда оно будет найдено. - person Matt Lacey; 05.07.2011
comment
Проект доступен по ссылке. Метод LoadData в MainViewModel создает и добавляет в коллекцию новые объекты ItemViewModel. Затем коллекция сериализуется в IsolatedStorage. Затем элементы очищаются. Строка 84 - это то, что я ожидаю, но пользовательский интерфейс не обновляется. Строки с 88 по 92 — это моя работа по обновлению пользовательского интерфейса. Итерация действительно необходима? Любые мысли приветствуются. - person Jason James; 06.07.2011
comment
Было бы неплохо узнать, что вы использовали инструменты 7.1. Я только что загрузил ваш образец на машину, на которой не запущена бета-версия манго, и не смог ее открыть. :( - person Matt Lacey; 06.07.2011
comment
Извините, что не упомянул об этом. Дело в манго не было корнем моей проблемы (по крайней мере, я так не считал), и поэтому я просто забыл упомянуть об этом. В любом случае, спасибо, что нашли время, чтобы загрузить его и помочь мне. - person Jason James; 07.07.2011

В конце концов докопались до сути. Это было связано с определением ObservableCollection. Из коробки это выглядит так

    public ObservableCollection<ItemViewModel> Items { get; private set; }

Однако NotifyPropertyChanged срабатывает только тогда, когда свойство определено как таковое:

    private ObservableCollection<ItemViewModel> _items;
    public ObservableCollection<ItemViewModel> Items
    {
        get
        {
            return _items;
        }
        private set
        {
            if(_items != value)
                _items = value;
            NotifyPropertyChanged("Items");
        }
    }

Элементы реализовали INotifyPropertyChanged, но он никогда не вызывался, когда объект Items был назначен.

Теперь все работает так, как ожидалось, и нет необходимости перебирать загруженную коллекцию и добавлять ее в Items ObservableCollection.

person Jason James    schedule 05.07.2011
comment
Это был мой первый вопрос и мой ответ. Вы сказали, что уже занимаетесь этим. - person Matt Lacey; 06.07.2011
comment
@Matt Моя интерпретация вашего ответа не привела меня к окончательному выводу, хотя, оглядываясь назад, ваш вопрос содержал указатель на окончательное решение. Свойства класса, экземпляром которого был создан Item, реализовывали NPC, однако теперь для меня очевидно, что недостаточно иметь только свойства класса, реализующие NPC, и свойство, которое реализует класс (объект) также должен вызвать событие NPC, чтобы обновить пользовательский интерфейс. Еще раз спасибо, что остаетесь со мной в этом. - person Jason James; 07.07.2011