-1

I'm using Prism 6.3 to build a simple cloud client with seafile.
After the user logs in, I navigate to a sidebar in a side region (SidebarRegion). OnNavigatedTo are the libraries loaded in a collection and displayed.

When the selected library changes, I navigate to a new ItemsView instance (ContentRegion) and load the items (from the library) so they can also be displayed.

If now clicked on an item, I navigate to another side region to display detailed information about the item.

public SeafDirEntry SelectedItem
{
    get { return _selectedItem; }
    set
    {
        if (!SetProperty(ref _selectedItem, value) || value == null)
            return;

        var parameter = new NavigationParameters {{ "item", _selectedItem }};
        _regionManager.RequestNavigate(_regionNames.InfoBarRegion, new Uri("ItemInfoView", UriKind.Relative), parameter);
    }
}

There's also a delete button, which is hooked to a command which deletes the item

Now, after the item/file is deleted from the server, I hooked up the PubSubEvent to reload the items from the library with the RefreshItemsAsync() method. After the items collection is overwritten, the PropertyChangedevent throws a NullReferenceException, even if I try this:

public ObservableCollection<SeafDirEntry> Items
{
    get { return _items; }
    set
    {
        if (value == _items)
            return;

        _items = value;
        RaisePropertyChanged(); // <- throws here
        // SetProperty(ref _items, value); <- same result
    }
 }

I tried also to remove the item from the collection with the item as payload of the PubSubEvent, but it also throws an NullReferenceException at _items.Remove(itemFromPayload).
Even if I refresh the collection manually by a button, same result.
The ItemsViewModel gets only created once per library and resists even after switching between them, so the reference should exists.

What did I miss out here?

  • Possible duplicate of [What is a NullReferenceException, and how do I fix it?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Rafael Apr 18 '17 at 12:49
  • @SvenLion Really, did you even read my whole explanation? I know where the exception is, but I don't know where the reference gets lost. I also know the linked post, but it won't help much finding this wpf specific error and a solution to it. –  Apr 18 '17 at 12:53
  • 2
    It's not a wpf specific error, because a NullReferenceException is always an issue with something being set to null/being uninitialized. – Rafael Apr 18 '17 at 12:58
  • Did you hook an event-handler to the event? – HimBromBeere Apr 18 '17 at 12:59
  • 1
    @SvenLion Ok, but a wpf/uwp/xamarin/forms mvvm scenario. Where I should not have _items initialized? When the `ItemsViewModel` gets constructed, `OnNavigatedTo` gets called afterwards which calls `RefreshItemsAsync` if the library param isn't empty. I checked while debugging and whether the param is empty, nor is `_items` not set to value before calling `RaisePropertyChanged` –  Apr 18 '17 at 13:04
  • @HimBromBeere In the `ItemsViewModel` ctor I hook to it with `eventAggregator.GetEvent().Subscribe(OnFileDeleted);`. `OnFileDeleted` calls `RefrehItemsAsync`. –  Apr 18 '17 at 13:07
  • @Richardissimo Well, you're right. If I initialize `_items` in the constructor with an empty collection, it works flawless. But even if I checked that the data in NavigatedTo is "valid", in the setter not null and waited enough time for the async method to finish? If you add your comment as answer I'll mark it as correct, thanks. –  Apr 18 '17 at 13:18
  • 1
    ObservableCollection properties should be read only, and set on construction of the view model. OCs implement INotifyCollectionChanged for a reason. Also, note, if you had designed it that way from the beginning you wouldn't have even had this problem. Tada! –  Apr 18 '17 at 16:04

1 Answers1

1

AFAICT _items is not initialised unless you navigate to it with "valid" data, which is loaded asynchronously. So _items could be "null" well after the page has been displayed (at which point the XAML would presumably try to use a collection which is null). Consider instead the approach of always initialising it to an empty collection, and then populating that collection (on the correct thread) with the data you want displayed. That's how ObservableCollections are meant to work.

Richardissimo
  • 5,083
  • 2
  • 12
  • 32