Why is CollectionView.CollectionChanged protected? - wpf

I want to monitor changes to a CollectionView but the CollectionChanged event is protected. How should I do this? Surely there must be a way to subscribe to this event - the list controls must do this somehow.
I can cast SourceCollection to INotifyCollectionChanged and add an event there, but that seems unneccesarily messy.

... the list controls must do this somehow.
I can cast SourceCollection to INotifyCollectionChanged and add an event there, but that
seems unneccesarily messy.
In fact, that's exactly how the list controls do it. This is from ItemsControl's source code (found via http://www.dotnetframework.org/):
((INotifyCollectionChanged)_items).CollectionChanged += new NotifyCollectionChangedEventHandler(OnItemCollectionChanged);
You are probably meant to expose your CollectionViews as the interface, ICollectionView, which itself inherits INotifyCollectionChanged as well as providing CollectionView properties like CurrentItem.

Why aren't you using an ObservableCollection instead?

Related

Combine CollectionChanged and PropertyChanged notifications in ObservableForPropertyHelper with ReactiveUI

I have a ReactiveObject ViewModel that contains an IObservableCollection and a regular property that raises INPC when it is modified (ie, vanilla WPF).
I want to implement an ObservableForPropertyHelper backed read-only that will re-evaluate whenever the regular property changes, or the collection changes (raises its CollectionChanged) event.
I know I can implement this using WhenAnyValue for the regular property, FromEventPattern to create an observable for the collectionchanged event, and then stitching them together with a CombineLatest. My question is - is there a less god-awful way to do this? Is there a built in ReactiveUI functionality that will help me achieve this?
You could swap the ObservableCollection for ReactiveUI's ReactiveCollection which exposes an IObservable for when the collection changes.
You could also use ReactiveUI's ObservableForProperty instead of WhenAny, which will be a little more succinct as you are only observing 1 property.
Other than that, what you have described is how I would do it.

List<> collection does not update the View in MVVM

I used the List<Person> collection as the ItemsSource for the DataGrid control.
But it did not update the View if i remove the item from the List collection. I was struggling for a long time for the solution.
Then Instead of the List<Person> collection in my ViewModel. I changed this into ObservableCollection<Person> collection. Now it updates the view when ever there is a change in the collection.
I am not sure why it updates only for ObservableCollection<Person> ? Anyone ?
Well its in the name. A simple List doesn't tell the ui to update, in other words "the view can't observe the list". There is no weird magic behind Databinding. WPF and DataBinding needs the Data model to tell them "this is new" or "this is changed", you propably already saw INotifyPropertyChanged, INotifyCollectionChanged is the same but for collections, and the List<> doesn't implement it, ObservableCollection does.
Because List does not implement INotifyCollectionChanged
Because the update of a databinding is not a kind of magic, there are several requirements to make databinding working correctly. If you have a single property to bind on this property must be either a dependency property or its parent class must implement the INotifyPropertyChanged interface to notify the wpf binding system about changes of the property value.
For a collection there is a simelar mechanism: it must implement INotifyPropertyChanged to inform the wpf binding system about removed/moved/added items.
See here for more details: http://msdn.microsoft.com/en-us/library/system.collections.specialized.inotifycollectionchanged.aspx
ObservableCollection<T> fires change events every time you change the items in the collection. List<T> doesn't. That's the reason.
DataBinding is lazy. If you don't tell your view that something has changed, it won't bother updating. Under the hoods, WPF DataBinding registers for change notifications, so that your ViewModel can tell the view when it has changed. It does this with interfaces like INotifyPropertyChanged and INotifyCollectionChanged.
ObservableCollection<T> implements the interface INotifyCollectionChanged. This interface defines the event CollectionChanged, which your View basically attaches its own event handler to. That handler will update the view when the event is raised by the collection.

Initiate change of a DependencyProperty of a ViewModel with a Event of another Thread

I want to change a DependencyProperty of my ViewModel from a class which connects the application to a database.
This class raises events which should initiate a change of some properties in my ViewModel.
How can I realize that? I don't have the Dispatcher of the View.
I'm assuming you don't really have dependency properties on your viewmodels but rather normal C# properties which raises the PropertyChanged event.
If so, you should be fine already. Modify your properties from your background thread (normal concurrency issues apply obviously) and when they are bound to a WPF element's Dependency Property the runtime system will take care of marshalling the change to the proper thread (by using the view's Dispatcher object)
This works for normal properties, I'm not sure it works for ObservableCollections.
There are also different approaches for doing the marshalling inside the viewmodels. The simplest way is to just store the value of Dispatcher.CurrentDispatcher in your viewmodel's constructor. This works as long as your viewmodels are created on the UI thread.
One immediate solution to the problem is to capture the view's Dispatcher and store it on the view model when you create it, so you can Invoke/BeginInvoke the change to it in response to the event.
That being said, you should consider making your viewmodels use INotifyPropertyChanged with CLR properties rather than DependencyProperties to avoid issues like this. That way, any thread can make changes to your viewmodel and have the results reflected in the view.

How to implement INotifyPropertyChanged and observableCollection in MVVM pattern?

I have an ObservableCollection of Products in the Model, and I want the ViewModel to listen to any changes in the ObservableCollection of Products.
Im not sure about how to go and implement it. Ive read several tutorials, but most of them are not MVVM specific.
Should i implement the INotifyPropertyChanged in the ViewModel class, how do I specify that i want to listen to the OberserableCollection of Products?
Thanks :)
I know this has already been answered, but there is more to consider.
1) a ViewModel should implement INotifyPropertyChanged, that's one of the things that makes it a ViewModel. Even in the unlikely case that the only property it exposes is the ObservableCollection, it will need to raise property changed when the actual ObservableColelction property is changed (more on this in item 3)
2) do you really want the ViewModel to listen for these changes or the View? Those are two different things. The ViewModel should hold an ObservableCollection which is then bound to the View. What you want is for the View to react to those changes. In that case, Brandon is correct that ObservableCollection does this for you out of the box. So the View has an instance of the ViewModel set as a DataContext and some visual element in your View is bound to the ObservableCollection (like an ItemsSource on a ListBox).
3) the exception is the ObservableCollection property itself in the ViewModel. While ObservableCollection implements INotifyPropertyChanged, that is part of the collection object: when that object reference changes (like it is recreated) in the ViewModel, then the ViewModel still needs to report that the Property for the ObservableCollection has changed.
Just some thoughts.
ObservableCollection already implements INotifyPropertyChanged, so you don't need to.

what is the difference between TwoWay databinding and ObservableCollection?

As i was reading about ObservableCollection i came to know that it implements INotifyPropertyChanged which means whenever the view changes it's underlying collection also gets updated automatically which is exactly what is the purpose of TwoWay databinding. So, what is the difference between ObservableCollection and TwoWay databinding?
Thanks in advance :)
The two "things" TwoWay databinding and ObservableCollection are different things which can collaborate, but are not directly linked. Databinding is a concept and ObservableCollection is an implementation of an interface (INotifyCollectionChanged) which is used in the implementation of the concept of databinding in the .NET framework. In itself, INotifyCollectionChanged is a small part of this implementation.
In fact you can use TwoWay databinding without ObservableCollections and ObservableCollections without databinding.
Databinding is a mecanism allowing you to bind a business object property (Often a ViewModel property) to an UI property. OneWay Databinding provides support for update of UI when the object is changed (which requires implementation of INotifyPropertyChanged and/or INotifyCollectionChanged on the business object). TwoWay Databinding provides twoway support as its name suggest it: Object => UI (like OneWay do) AND UI => Object. UI to Object updates does not requires implementation of INotifyCollectionChanged nor INotifyPropertyChanged.
Observable collection now is interesting because it implements INotifyCollectionChanged, which makes it a good candidate to create databindable collections. But I use often INotifyCollectionChanged without databinding, and I am pretty sure you can find other collections which implement INotifyCollectionChanged (like PagedCollectionView)
Does it answer your question?
If you bind to your collection like this {Binding Path=MyCollection, Mode=TwoWay} then reference to collection will be updated but not its contents. Observable collection allows to track its contents changes, but not reference change (MyCollection.Clear() will trigger UI update, but MyCollection = anotherInstance will not).
The question is a little bit like "what's the difference between a horse and a cart?"
An ObservableCollection can be used for TwoWay databinding (to an ItemsControl).
It is more or less designed to make databinding easy.
Whenever a Control updates an ObservableCollection or the other way around, there is a DataBinding in the middle.
Object needs to implement INotifyPropertyChanged so you are able to bind to properties of this object.
TwoWayDatabinding tells databinding engine it needs to update properties both ways.
You are comparing apples and airplanes. Those are two completly different things.
Also ObservableCollection also implements INotifyCollectionChanged that allows to notify its items changed, not only properties.

Resources