This question already has an answer here:
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.
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 linecustom.
SessionCollection.Add(..)
gets executed you get a null exception. ASSessionCollection
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())):
See below where the exception occurs:
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 theObservableCollection
typeYour
Session
model is fine with theObservableCollection
property but I would call itSessions
. On the other hand i see no reason to haveCustomSession
at all - try to remove itVIEW MODEL
It knows about your
Sessions
type but it must not know about what is aDependencyObject
.In the code below i often leave
sessionsCollection
property as a getter only. If I implement the set i always follow theINotifyPropertyChanged
patternVIEW
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.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
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:If you do not initialize
_sessions
it will have no object its referencing to. This is what theNULL
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