1

I have WPF application where I am following MVVM. I have a class called Session as follows: Session.cs

 public class Session:ObservableCollection<Session>
    {
        public int value { get; set; }
        public string name { get; set; }



    }

    public class CustomSession:DependencyObject
    {
        public static readonly DependencyProperty SessionCollectionProperty =
            DependencyProperty.Register("SessionCollection", typeof(Session), typeof(CustomSession), new PropertyMetadata());

        public Session SessionCollection
        {
            get { return (Session)GetValue(SessionCollectionProperty); }
            set { SetValue(SessionCollectionProperty, value); }
        }


    }

I have ViewModel as follows: ViewModel.cs

 public class ViewModel:BindableBase
{
    private ObservableCollection<Session> _sessions;
            public ObservableCollection<Session> sessionsCollection
            {
                get { return _sessions; }
                set { SetProperty(ref _sessions, value); }
            }

    public ViewModel()
            {
    sessionsCollection = allSessions();
    }

    public ObservableCollection<Session> allSessions()
            {
                CustomSession custom = new CustomSession();
                custom.SessionCollection.Add(new Session() { name = "LocateSession", value = 10 }); //System.Null Reference Exception.
                custom.SessionCollection.Add(new Session() { name = "TrackSession", value = 20 });
                custom.SessionCollection.Add(new Session() { name = "MonitorSession", value = 25 }); 
                custom.SessionCollection.Add(new Session() { name = "MassSnapshot", value = 18 });
                custom.SessionCollection.Add(new Session() { name = "MassContinuous", value = 9 });
                return custom.SessionCollection;
            }
}

I have a UI where I want to bind this Observable Collection. Whenever I try to add in an item like custom.SessionCollection.Add(new Session() { name = "LocateSession", value = 10 }); I get Null Reference exception. I want to populate the ObservableCollection from the ViewModel. How do I do it. Please help.

nikhil
  • 1,578
  • 3
  • 23
  • 52
  • Additionally to my answer I would check if you really want Session to be a collection of Sessions. Could it be that you meant to implement the INotifyPropertyChanged interface? – Nicholas Schuster Feb 11 '16 at 00:11
  • Please pay attention to what you've marked as the answer. By marking incorrect answers and leaving random comments on other answers you make your question (and its solution) worthless to anyone else. This site gains value from accuracy and completeness; it loses value when the OP of a question can't be bothered to do things correctly. – slugster Feb 11 '16 at 09:52
  • For those about to cast a reopen vote: think carefully. This is not a question about how to properly define a dependency property, it's a question about *"I have a Null Reference Exception, how do I fix it?"*. While it can be answered by telling the OP what value to set (as all these questions can be), there is no value to be gained by reopening it, it's still a duplicate. – slugster Feb 11 '16 at 11:04
  • @nikhil i suggest you edit your question to be more MVVM concerned and lose its focus in the NRE so that the community can gain with it – Luis Filipe Feb 11 '16 at 22:51
  • @slugster: I agree with you regarding the NRE. But, my two cents, when i first read and answered this question i focused on the MVVM architecture. I commented above so that asker edits the question to be mvvm-focused and the community can gain from it. – Luis Filipe Feb 11 '16 at 22:53
  • Ok Im sorry but if I understood you correctly do you want me to change the Tag of the question? – nikhil Feb 11 '16 at 22:54
  • @LuisFilipe That's cool - just because a question is a duplicate that doesn't mean it can't or shouldn't be answered - it simply means it shouldn't be *reopened*. – slugster Feb 11 '16 at 23:14
  • @nikhil tags are (IMHO) perfect. i believe your difficulty was related with the added unnecessary DependencyObject prop in your ViewModel. I'd say that means a not so well understood MVVM pattern, I would change the question to highlight the challenges of setting up a clean and simple mvvm solution - i reinforce this statement because once it comes clear the mvvm simplicity all the dependency object complexity goes away - sorry for the long comment – Luis Filipe Feb 11 '16 at 23:19
  • @nikhil No, your tags are fine. It was the answer that you marked that needed attention - if it is marked as the answer then it should be technically correct and accurate, otherwise it is useless (and even misleading) to others who look at this question. This is not a criticism of Nicholas (I've submitted incorrect answers in the past), it's more of a reminder to you that others look at your question, they may have the exact same issue or be using your question as a guideline, therefore you want to keep it useful. – slugster Feb 11 '16 at 23:19

3 Answers3

3

First of all your Null reference exception will go away if you follow the correct mvvm approach which i'll describe (partially) below

MODEL

Following MVVM enforces that only you presentation layer knows about WPF. The exception i accept is the ObservableCollection type

Your Session model is fine with the ObservableCollection property but I would call it Sessions. On the other hand i see no reason to have CustomSession at all - try to remove it

public class Sessions:ObservableCollection<Session>
    {
        public int value { get; set; }
        public string name { get; set; }
    }

VIEW MODEL

It knows about your Sessions type but it must not know about what is a DependencyObject.

In the code below i often leave sessionsCollection property as a getter only. If I implement the set i always follow the INotifyPropertyChanged pattern

public class ViewModel: BindableBase
{
    private Sessions _sessions;
    public Sessions sessionsCollection
    {
       get { return _sessions; }
    }

    public Session SelectedSession
    {
        get;set; //properly implemented with the INotifyPropertyChanged
    }

    public ViewModel()
    {
      sessionsCollection = allSessions();
    }

    public Sessions allSessions()
    {
                var custom = new Sessions();//notice this is already a collection
                custom.Add(new Session() { name = "LocateSession", value = 10 }); //System.Null Reference Exception.
                custom.Add(new Session() { name = "TrackSession", value = 20 });
                custom.Add(new Session() { name = "MonitorSession", value = 25 }); 
                custom.Add(new Session() { name = "MassSnapshot", value = 18 });
                custom.Add(new Session() { name = "MassContinuous", value = 9 });
                return custom;
            }
}

VIEW

In the WPF simply bind some combobox, listbox, etc to the Sessions property. I don't have wpf right here so the syntax might be wrong.

<ListBox Items={Binding sessionsCollection} SelectedItem={Binding SelectedSession} />

I'd like to add that although the original question only referred to NRE it only happened because it was exposing DependencyObject in the wrong scope. I truly believe my refactoring helps to understand the simplicity (and advantages) of MVVM

Luis Filipe
  • 8,488
  • 7
  • 48
  • 76
3

I don't think that not initializing the _sessions field caused the null error. You have never directly used that field(or property). It was only assigned so can't cause null exception.

Your problem was that your DependencyProperty SessionCollection doesn't have a default value. So when line custom.SessionCollection.Add(..) gets executed you get a null exception. AS SessionCollection will have null default value.

Try to change your property like this(In PropertyMetadata constructor give a default value, as I have given a new object (new Session())):

public static readonly DependencyProperty SessionCollectionProperty =
        DependencyProperty.Register(  "SessionCollection"
                                    , typeof(Session)
                                    , typeof(CustomSession)
                                    , new PropertyMetadata(new Session())
                                    );

    public Session SessionCollection
    {
        get { return (Session)GetValue(SessionCollectionProperty); }
        set { SetValue(SessionCollectionProperty, value); }
    }

See below where the exception occurs:

enter image description here

Kylo Ren
  • 8,551
  • 6
  • 41
  • 66
-2

If you are trying to fill this from code (which I assume you do) the problem is that you never initialized _sessions. So just do this simple code exchange:

// old
// private ObservableCollection<Session> _sessions;

// now
private ObservableCollection<Session> _sessions = new ObservableCollection<Session>();

If you do not initialize _sessions it will have no object its referencing to. This is what the NULL reference means. If you try to access it anyway you will run into an error because it does not know which object you mean.

Edit

I think I got confused with the different variables here. As mentioned in the comments this should actually not solve the problem as you are accessing a different property. However: The general problem stays the same (accessing a collection that has not been initialized). To solve that problem I would recommend the solution proposed by @Kylo-Ren