Reputation: 85
An ObservableCollection is self-contained when it comes to raising the CollectionChanged event because it implements INotifyPropertyChanged and INotifyCollectionChanged. So i think , we don't need to implement INotifyPropertyChanged again.
but i have seen some example where folks are defining ObservableCollection as property and raising property changed event in setter. i don't understand why this is done again or in better words why they are Raising property changed event in setter(see below code). As we already know that ObservableCollection automatically raises when add,update is done, then we need not to raise again.right?
please clarify my doubt.
public class TheViewModel()
{
private ObservableCollection<Camper> _campers;
public ObservableCollection<Camper> Campers
{
get { return _campers; }
set
{
if (Equals(_campers, value)) return;
_campers = value;
RaisePropertyChanged("Campers"); //Or however you implement it
}
}
Upvotes: 1
Views: 531
Reputation: 2620
If you set Campers to point to a new instance, that RaisePropertyChanged will do the job for you. Otherwise you will have a reference to the old instance and the View will remain out of sync. The other solution to this is, every time you set Campers to point to a new collection, set again the ItemsSource for your DataGrid or ListView or whatever control you use.
Indeed this works as long as you Add or Remove items from your collection. To conclude, that's the difference, when you set again
Campers = new ObservableCollection<Camper>();
your RaisePropertyChanged will be triggered.
Code update:
XAML:
<Window x:Class="ObservablePropertyChanged.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel>
<ListView ItemsSource="{Binding items}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Content="Change collection" Click="btnChangeCollection_Click"/>
</StackPanel>
</Grid>
Code behind:
public partial class MainWindow : Window
{
public ObservableCollection<string> items { get; set; }
public MainWindow()
{
InitializeComponent();
items = new ObservableCollection<string>();
items.Add("One");
items.Add("Two");
this.DataContext = this;
}
private void btnChangeCollection_Click(object sender, RoutedEventArgs e)
{
items = new ObservableCollection<string>();
items.Add("Three");
items.Add("Four");
}
}
As i don't have INPC interface implemented and no PropertyChanged added on the set of the items collection, after clicking the Button you will not get the View updated with items "Three" and "Four".
And here is another way to accomplish this behavior:
public ObservableCollection<string> items
{
get { return (ObservableCollection<string>)GetValue(itemsProperty); }
set { SetValue(itemsProperty, value); }
}
// Using a DependencyProperty as the backing store for items. This enables animation, styling, binding, etc...
public static readonly DependencyProperty itemsProperty =
DependencyProperty.Register("items", typeof(ObservableCollection<string>), typeof(MainWindow), new UIPropertyMetadata(null));
Using this dependency property, the ListView will remain in sync.
Upvotes: 2