I have a view model that exposes a ObservableCollection<TInheritor> collection as IEnumerable<TBaseInterface> (for the covariance). If I bind that property to the ItemsSource property on a ListBox, is that ListBox still smart enough to use my source as an ObservableCollection?
Yes it will do that, there shouldn't be any problems using an ObservableCollection like this. Here is an example: http://www.c-sharpcorner.com/UploadFile/e06010/observablecollection-in-wpf/
Related
I am pretty new to WPF MVVM, so pardon me if I understood MVVM concepts wrongly.
I have a DataGrid in my View, which I have bound the ItemsSource to an ObservableCollection<M> in the ViewModel. The M class is a Model class. However, the M class has bool properties, which are to be displayed in the DataGrid as "Yes/No" strings.
Currently, I am using a Converter to convert the bool value to string. But, it just feels wrong for the ViewModel to expose a list (ObservableCollection) of a Model to the View. I have also read that in MVVM, conversions should be done at ViewModel. So, what is the right way to implement this the MVVM way for a DataGrid?
In an ideal world, you would wrap your Model objects in their own ViewModel so that your ObservableCollection contains a ViewModel type with those bool Model properties converted to Yes/No string properties.
However, in a pragmatic world, if you are not editing those values, I wouldn't bother except to note that if you are exposing many of those bool properties and have many thousands of rows, you will take a performance hit on rendering the grid while the DataGrid instantiates a Converter per property and row.
Using converters is not a wrong way. As per my suggestion, you should bind the data as you're doing now and in the view you can create and use a BoolToStringConverter for converting the boolean value to yes or no.
Well, I'm confused.
If my control has dependency property ItemsSource of IEnumerable type and user binds collection to it what object do I have in DependencyPropertyChangedEventArgs.NewValue?
As far as I know CollectionView is implicitly created for collections and I expect args.NewValue to be of type ICollectionView.
From this blog:
When a user binds a WPF property to a collection of data, WPF
automatically creates a view to wrap the collection, and binds the
property to the view, not the raw collection. This behavior always
happens, and is independent of CollectionViewSource.
But debugger (VS 2012, .net v.4.0) shows me that I receive original raw collection in NewValue. (BindsDirectlyToSource is not set and equals false by default)
How can this be?!
I cannot understand how in this case WPF controls support sorting, grouping and filtering.
How and when is CollectionView injected and used?
Maybe the following extract from the Remarks section in CollectionView answers your question:
In WPF applications, all collections have an associated default
collection view. Rather than working with the collection directly, the
binding engine always accesses the collection through the associated
view. To get the default view, use the
CollectionViewSource.GetDefaultView method. An internal class based on
CollectionView is the default view for collections that implement only
IEnumerable. ListCollectionView is the default view for collections
that implement IList. BindingListCollectionView is the default view
for collections that implement IBindingListView or IBindingList.
Alternatively, you can create a view of your collection in Extensible
Application Markup Language (XAML) by using the CollectionViewSource
class and then bind your control to that view. The
CollectionViewSource class is the XAML representation of the
CollectionView class. For an example, see How to: Sort and Group Data
Using a View in XAML.
So if you do not explicitly bind to a CollectionViewSource, a collection binding is always made to the original collection (what you get in NewValue), but access to the collection (e.g. get an item by index) is always done through the default view. Therefore the statement "binds the property to the view, not the raw collection" is not exactly true.
A quick test revealed that GetDefaultView returns a System.Windows.Data.ListCollectionView for my bound ObservableCollection.
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.
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.
I'm trying to understand the basic MVVM design approach when using ItemsControl by binding it via DataTemplates to ObservableCollections on the ViewModel.
I've seen examples that bind to ObservableCollections of strings, Views, and ViewModels.
Binding to strings seems to be only for demos, it is the binding to "ViewModels that contain collections of Views that contain collections of ViewModels" that the power of WPF seems to really come out.
For those of use proficient in the MVVM pattern, what is your standard approach to binding ItemsControl, ListView, ListBox to collections in a ViewModel? I'm looking for advice from experience like this:
always use ObservableCollection<...> and never List<...> because...
something better than ItemsControl to display a collection is...
in order to get filtering to work in your ViewModel instead of code-behind, use...
use collections of Views when ... and collections of ViewModels when...
90% of the time I create an ItemsControl and bind it to an ObservableCollection of Views which have their own ViewModels...
I would use an ObservableCollection of ViewModels for the following reasons:
ObservableCollection already has events available for signaling when it has been modified (e.g. when items are added/removed from the collection).
We're at the ViewModel 'layer' so it provides cleaner separation to have a ViewModel contain a collection of ViewModels rather than Views
If it is necessary to modify or get data from items within the collection you can more easily modify/access that data if the items are ViewModels (if they're views you'll frequently be casting the View's DataContext or accessing its UI elements).
I like using an ObservableCollection of ViewModels. The view that binds to the collection can define a DataTemplate that gives the ViewModel its look. This leads to less coupling among the components.
I have the same question, but replace the "view" with "model". :)
I have a MODEL with a collection of other models.
I want my viewmodel to have an observable collection of other viewmodels, but once I instantiate it like that - the connection between the model collection content is lost.
Do I now need to start wiring all the events from the viewmodels observable collection back to the models collection?