ObservableCollection not updating View

I am just starting out with MVVM and hit the barrier and hope someone can help me. I am trying to create a simple view with two lists. The selection from the first list will be filled with the second list. I have a class that stores information that I want to bind.

MyObject Class (Observable Object - only the base class that implements INotifyPopertyChanged)

public class MyObject : ObservableObject { String _name = String.Empty; ObservableCollection<MyObject> _subcategories; public ObservableCollection<MyObject> SubCategories { get { return _subcategories; } set { _subcategories = value; RaisePropertyChanged("SubCategories"); } } public String Name { get { return _name; } set { _name = value; RaisePropertyChanged("Name"); } } public MyObject() { _subcategories = new ObservableCollection<EMSMenuItem>(); } } 

In my view model, I have two ObservableCollections created

 public ObservableCollection<EMSMenuItem> Level1MenuItems { get; set; } public ObservableCollection<EMSMenuItem> Level2MenuItems { get; set; } 

In my ViewModel constructor, I have:

 this.Level1MenuItems = new ObservableCollection<EMSMenuItem>(); this.Level2MenuItems = new ObservableCollection<EMSMenuItem>(); this.Level1MenuItems = LoadEMSMenuItems("Sample.Xml"); 

This works great for Level1 elements and they display correctly in the view. However, I have a command that is called when the user clicks an item in a list that has the following:

 Level2MenuItems = ClickedItem.SubCategories; 

For some reason, this does not update the user interface of the second list. If I put a breakpoint in this place, I see that Level2MenuItems has the correct information stored in it. If I write a foreach loop and add them separately to the Level2MenuItems collection, it will display correctly.

Also, as a test, I added the following to the constructor:

 Level2MenuItems = Level1MenuItems[0].SubCategories; 

And it is correctly updated.

So, why would the code work as expected in the constructor or when going through it, but not when the user clicks on an item in the list?

+8
c # wpf mvvm observablecollection
source share
3 answers

You need to raise a notification of a change in the Level2MenuItems property.

Instead

 public ObservableCollection<EMSMenuItem> Level2MenuItems { get; set; } 

you need

 private ObservableCollection<EMSMenuItem> _level2MenuItems; public ObservableCollection<EMSMenuItem> Level2MenuItems { get { return _level2MenuItems; } set { _level2MenuItems = value; RaisePropertyChanged("Level2MenuItems"); } } 

The reason the first one works in the constructor is because the binding has not yet taken place. However, since you change the link by executing the command that occurs after the binding, you need to report that it changed

+6
source share

You need to make your poco class in the implementation of the ObservableCollection INotifyPropertyChanged.

Example:

 <viewModels:LocationsViewModel x:Key="viewModel" /> . . . <ListView DataContext="{StaticResource viewModel}" ItemsSource="{Binding Locations}" IsItemClickEnabled="True" ItemClick="GroupSection_ItemClick" ContinuumNavigationTransitionInfo.ExitElementContainer="True"> <ListView.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Name}" Margin="0,0,10,0" Style="{ThemeResource ListViewItemTextBlockStyle}" /> <TextBlock Text="{Binding Latitude, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Style="{ThemeResource ListViewItemTextBlockStyle}" Margin="0,0,5,0"/> <TextBlock Text="{Binding Longitude, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Style="{ThemeResource ListViewItemTextBlockStyle}" Margin="5,0,0,0" /> </StackPanel> </DataTemplate> </ListView.ItemTemplate> </ListView> public class LocationViewModel : BaseViewModel { ObservableCollection<Location> _locations = new ObservableCollection<Location>(); public ObservableCollection<Location> Locations { get { return _locations; } set { if (_locations != value) { _locations = value; OnNotifyPropertyChanged(); } } } } public class Location : BaseViewModel { int _locationId = 0; public int LocationId { get { return _locationId; } set { if (_locationId != value) { _locationId = value; OnNotifyPropertyChanged(); } } } string _name = null; public string Name { get { return _name; } set { if (_name != value) { _name = value; OnNotifyPropertyChanged(); } } } float _latitude = 0; public float Latitude { get { return _latitude; } set { if (_latitude != value) { _latitude = value; OnNotifyPropertyChanged(); } } } float _longitude = 0; public float Longitude { get { return _longitude; } set { if (_longitude != value) { _longitude = value; OnNotifyPropertyChanged(); } } } } public class BaseViewModel : INotifyPropertyChanged { #region Events public event PropertyChangedEventHandler PropertyChanged; #endregion protected void OnNotifyPropertyChanged([CallerMemberName] string memberName = "") { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(memberName)); } } } 
+1
source share

The Subcategories property should be read-only .

0
source share

All Articles