0

the following code is giving me a Null Reference Exception on the _items.Clear() step, and I can't work out why.

public void PlotDate()
    {
        if (_data == null) return;
        _items.Clear();
        _items.Add(new Graph
        {
            Name = "by date",
            Items = _data.GroupBy(e => string.Format("{0:yyyy-MMM}", e.Date))
            .Select(g => new Item { Key = g.Key, Value = g.Sum(x => x.Size) })
            .OrderByDescending(e => e.Value)
            .ToList()
        });
    }

_items is a bindable collection of Graphs which are displayed in a xaml frontend. In this instance the graph just shows a pie chart of the sum of all sizes in a series of dates. In the class, there are a few of these methods for showing different data which are almost identical, they basically just group the data differently.

The weird thing is that the first one always loads just fine, whichever one I pick, but then when I try to open a second one it throws the exception. When the view is first opened it also runs a method that populates _data and runs _items.Clear, so it works fine when _items is empty.

I've put breakpoints wherever I can think of to try and see what's going on but nothing is being set to null. Right before the _items.Clear step runs, _items has a count of 1, then it throws the exception immediately after the count goes down to 0.

I've also tried using _items.RemoveAt(0), and putting it after the new graph is added and it does the same thing.

What's going on??

Edit: I'll include this part which might be useful. The display on the UI binds to Items, which is determined by this so it might be where the issue is. I can't get any deeper though, looking at the definition for NotifyOfPropertyChange doesn't yield any useful information.

partial void OnItemsChanged();
        public BindableCollection<Graph> Items
        {
            get { return _items; }
            set 
            {
                if (value == _items) 
                    return;
                _items = value;
                OnItemsChanged();
                NotifyOfPropertyChange("Items");
            }
        }
braX
  • 9,702
  • 5
  • 16
  • 29
Antyla
  • 101
  • 2
  • 3
    Looks like `_items` is `null`. Could you set a *breakpoint* and check if it is? – Dmitry Bychenko Sep 23 '15 at 06:44
  • You say "it throws the exception immediately after the count goes down to 0". Does this mean the the `_items.Clear()` line executes correctly, count is 0 and it throws the exception on the next line? – vesan Sep 23 '15 at 06:46
  • No, so I set the breakpoint on `_items.Clear()` and check `_items` and the count is 1. Then I do a 'step into' and the exception appears on `_items.Clear()` and if I check `_items` again at that point, the count is 0, as it should be, but I'm not sure why the exception is coming up. – Antyla Sep 23 '15 at 06:53
  • What's the stack trace for the exception? – Damien_The_Unbeliever Sep 23 '15 at 06:57
  • It's pretty long but the last few lines are: at System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e) at Caliburn.Micro.BindableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e) at Caliburn.Micro.BindableCollection`1.ClearItemsBase() at Caliburn.Micro.XamlPlatformProvider.OnUIThread(Action action) at Caliburn.Micro.Execute.OnUIThread(Action action) at Caliburn.Micro.BindableCollection`1.ClearItems() at [...].StorageSummaryViewModel.PlotDate() in [...]\StorageSummaryViewModel.cs:line 113 – Antyla Sep 23 '15 at 07:02
  • 1
    please provide the part where you initiate _items object – Best_Where_Gives Sep 23 '15 at 07:15
  • also try `if (_items != null && _items.Any())` – Amit Kumar Ghosh Sep 23 '15 at 07:19
  • @Best_Where_Gives Here are the bits I can see that might be useful: at System.Windows.Data.BindingExpression.Activate(Object item) at System.Windows.Controls.ItemsControl.MS.Internal.Controls.IGeneratorHost.ClearContainerForItem(DependencyObject container, Object item) at System.Windows.Controls.ItemContainerGenerator.UnlinkContainerFromItem(DependencyObject container, Object item, IGeneratorHost host) – Antyla Sep 23 '15 at 07:50
  • @AmitKumarGhosh That doesn't seem to make any difference. – Antyla Sep 23 '15 at 07:51

3 Answers3

1

It is difficult to know what's wrong without the rest of the code. The exception might occur somewhere else when the Clear function is called. To help you debugging, you can configure VS to throw the NullReferenceException where it occurs by

Debug Menu -> Exceptions.. -> Common Language Runtime Exceptions -> System-> System.NullReferenceException -> Check Thrown

VS will stop at the line of code that throw exception.

Viet Nguyen
  • 386
  • 2
  • 11
  • Unfortunately the exception still appears at the same place when I do that. Doing the whole code would be tricky as there are a _lot_ of codependent parts to include. I thought it was fairly self-explanatory though, it's just a list that won't clear. :\ – Antyla Sep 23 '15 at 07:48
  • Usually, at least one of the objects in the line of code where VS breaks would be `null` for it to throw this exception. I've never seen anything that throw a NullReferenceException when none of the objects is `null`. What object is your `_items` binding to? Perhaps the binding object is made `null` insteads. – Viet Nguyen Sep 23 '15 at 07:59
0

Maybe _items is null. Just add a breakpoint on _items.Clear() line and debug your application.

ohadinho
  • 5,866
  • 14
  • 61
  • 111
0

From the stack trace I can see the exception is thrown in OnCollectionChanged event which is fired by Clear() call. So you should check what happens in this event and it should be shown before

System.Collections.ObjectModel.ObservableCollection1.OnCollectionChanged(Notify‌​CollectionChangedEventArgs e)

line in stack trace.

wziska
  • 348
  • 1
  • 4
  • 15
  • Here are the lines beforehand, I'm not sure if they'll be useful: at System.Windows.WeakEventManager.DeliverEventToList(Object sender, EventArgs args, ListenerList list) at System.Windows.WeakEventManager.DeliverEvent(Object sender, EventArgs args) at System.Windows.Data.CollectionView.OnCollectionChanged(NotifyCollectionChangedEventArgs args) at System.Windows.Data.ListCollectionView.RefreshOverride() at System.Windows.Data.CollectionView.RefreshInternal() – Antyla Sep 23 '15 at 08:06
  • There is this which may be useful, although it's not where the exception is thrown and I can't access the definition for NotifyOfPropertyChange. `partial void OnItemsChanged(); public BindableCollection Items { get { return _items; } set { if (value == _items) return; _items = value; OnItemsChanged(); NotifyOfPropertyChange("Items"); } }` – Antyla Sep 23 '15 at 08:08