I've been struggling with this problem for hours now:
I'm building an UWP application in the MVVM pattern.
Problem: I can't get my ListView's ItemSource to update/rebind to a new instance of ObservableCollection, when I change the ItemSource's property's value, even though I have implemented IPropertyChanged on the property.
Details: The page I am working on has a ListView which ItemSource is bound to an observable collection:
Page:
<ListView ItemsSource="{Binding Orders}" x:Name="OrderListView"><!--Inner bindings works fine--></ListView>
ViewModel:
public ObservableCollection<Order> Orders {
get { return _Orders; }
set { Set(ref _Orders, value); }
}
private ObservableCollection<Order> _Orders;
(...)
//Property changed implementation from video (06:48): https://mva.microsoft.com/en-US/training-courses/windows-10-data-binding-14579?l=O5mda3EsB_1405632527
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
//If property is updated with, raise property changed, else don't
public bool Set<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (Equals(storage, value))
return false;
storage = value;
RaisePropertyChanged(propertyName);
return true;
}
When pressing a button in the UI:
<Button Content="Waiter" Click="Waiter_Click" Background="{Binding Waiter, Converter={StaticResource BoolToColorConverter}, FallbackValue='Yellow', TargetNullValue='Red'}"/>
It will tricker the "Waiter_Click" event handler in the code behind:
private void Waiter_Click(object sender, RoutedEventArgs e)
{
var viewModel = ((Button)sender).DataContext as OrderPageViewModel;
if (viewModel.Waiter) viewModel.Waiter = false;
else viewModel.Waiter = true;
}
The Waiter property is implemented, so it raises PropertyChangedEvent in the ViewModel:
public bool Waiter
{
get { return _waiter; }
set { Set(ref _waiter, value); FilterView(); }
}
private bool _waiter;
The button is updated in the UI - This works fine.
After setting the private field of _waiter, I also want to filter out some data that I don't want to show.
I do this in the FilterView(); method. This is done by creating a new ObservableCollection, and setting the Orders property:
public void FilterView()
{
var filteredOrderList = new ObservableCollection<Order>();
//Sorting is done
Orders = filteredOrderList;
}
Now. I thought that the code: Orders = filteredOrderList; would trigger the "setter" of Orders property, and raise the PropertyChanged event as it does with the button and all other UI elements that works fine - and tell the ListView to rebind to it. However it seems like the ListView is running on an old instance of the ObservableCollection, and does not care about my PropertyChanged event being fired...
I've debugged the program, and I see that filteredOrderList contains the data I want, and that Orders is changed. But it's like ViewList does not care about the PropertyChanged event is fired...
I don't want to add and remove items from the ObservableCollection because the filtering becomes very complicated... I just want to replace the Orders ObservableCollection with a new one, and let the ViewList reflect my changes...
Am I missing something? Can't I call PropertyChanged event multiple times? (I'm calling it once for the button update, and once for the Orders ObservableCollection to be changed).
Why is ListView not rebinding to the the new list? -Does ListView not care about PropertyChanged events being fired?
I will deeply appreciate any answer or workaround that will fix this or send me in the right direction.
Thank you, and sorry for long post.