Can you turn off selection syncing in WPF's CollectionViewSource? - wpf

I have several CollectionViewSource instances all used on the same ObservableCollection. I also have several controls that need to show filtered versions of the collection (hence the CollectionViewSources). The problem I'm having is that CollectionViewSource forces them to all have the same item selected. Is there some way to turn this off?
Thanks,
Jason Lewis

If you use the method (im not sure about this but CollectionViewSource in xaml probably does)
CollectionViewSource.GetDefaultView(this.ItemsSource);
multiple times it will only return the same ICollectionView (if we are talking about the same collection bound multiple times), this means if you apply a filter to one it apllies to all, also as the collection view tracks the current item the current item will be syncronised between the different views.
You can work around this by creating a CollectionView for each filter/selection you want to have by using
new CollectionView(this.ItemsSource as IList);
there are a few types that implement ICollectionView, CollectionView and ListCollectionView do. in the above code i did not get the default view i created a new one, so its filering/sorting is unique.
When you use items source wpf creates a collection view to wrap the collection, this collection view is the one that is returned in the GetDefaultView call, useful for every day situations but not the edge cases.
here is a blog post from bea that explains it a bit better

Related

how do i bind and manage synchronization of my model collection to an items control?

I want to bind an ObservableCollection of model items to an ItemsControl and be able to manage adding and removing items to and from that collection, as well as synchronize presence of member in the collection with views of user controls that represent those items.
but I realized that when I trying to remove the models, they are still there and the views are still displayed as the last time I added one.
I think my problem is that I can't understand how to manage the ViewModel and View that associated with the model that I trying to remove. do I also have to dereference the model from the ViewModel(or the ViewModel from the View) to let the GC do its work?
do I need to construct the ViewModel or Models in code-behind? or is it enough to declare the DataContext's type in the XAML, or if both are there it is redundant? (maybe some null reference caused this because there was no reference to remove?)
I'm new to WPF and MVVM and I think that question is pretty basic, but I didn't find any question about that integration of ItemsControl with ObservableCollection.

List or ObservableCollection?

Is there any difference in performance to use ObservableCollection, which (as I understand) refreshes view each time item added to collection, or instead use simple List collection, and refresh whole view when all elements already added?
And is the scenario with List as decried above even possible? How to implement this then?
I'm asking because my ItemsControl is slow, and I wonder if it would be better to use simple List instead ObservableCollection. I need to refresh the view only once at a time, when actually all elements already added to collection.
ObservableCollection<T> implements IList<T> just as List<T> does. The main difference is of course, that it implements INotifyCollectionChanged which allows WPF to bind to it.
The ObservableCollection<T> throws an event after each change so the UI can Refresh. If you are adding a lot of Items sequentially, it can have some impact to your performance but that is unlikely. You can test this rather simple by using the Constructor which takes a List:
var originalList = new List<SomeClass>();
foreach ([..])
{
originalList.Add(someInstance);
}
ObservableCollection<SomeClass> uiCollection = new ObservableCollection<SomeClass>(originalList);
This way you can create you complex List of objects and after its finished you can create an ObservableCollection out of it which you will Bind to on the UI.
If you don't plan to add or remove items dynamically at runtime, you might as well use a List<T> instead of an ObservableCollection<T>. The difference in performance will be negligible though.
The special thing about the ObservableCollection<T> is that it implements the INotifyCollectionChanged interface: https://msdn.microsoft.com/en-us/library/system.collections.specialized.inotifycollectionchanged(v=vs.110).aspx
WPF subscribes to the CollectionChanged event of any collection that implements this interface to listen for collection changes. So if you for some reason want to create your own custom collection that supports change notifications, you could create a class that implements this interface.
I strongly doubt that your performance issues is related to the type of source collection you are using though. You should make sure that UI virtualization is enabled and go trough the following list of suggestions on how to improve the performance of Controls in WPF: https://msdn.microsoft.com/en-us/library/cc716879(v=vs.110).aspx

WPF: How to create a collection that can be bound to

My app has a background thread that periodically retrieves data from an external source, in the form of key/value pairs. I would like to expose this data for binding, presumably by storing them in some kind of static(?) model, as the data will be needed by numerous views throughout my app. There are potentially hundreds of these keys, and may be different for each customer, so I can't simply create an INotifyPropertyChanged model with a property for each value.
The app has multiple views visible at any one time, and each of these will have numerous controls (usually textboxes) that I want to bind to individual items in the above collection. When a value in the collection is updated, any controls bound to only that item should change to reflect the new value. I'm assuming an ObservableCollection wouldn't be suitable here, as a change to a single item will result in all controls updating, regardless of which item they are bound to?
To throw a further complexity into the mix, some values (which are numeric) will need formatting for display, e.g. number of decimal places, or adding a suffix such as "volts". The formatting rules are user-defined so I can't hardcode them into (say) the XAML binding's StringFormat expression. Ideally I should be able to access both the raw value (e.g. for calculations), and the formatted version (for display purposes). I'm sure it must be possible to achieve the latter using some clever WPF feature!
I would appreciate any pointers on how I can solve these requirements.
Edit: it's worth mentioning that I've previously tried implementing the model as some kind of collection. The problem is that it won't be initially populated with all values, and these only get added some time later. When they do eventually get added, a bound control doesn't update - presumably because it wasn't initially able to bind to the missing value.
I would take a different approach, namely a variation of Event Aggregation. I would have a single class that manages the overall collection (probably a singleton class like franssu suggested), but instead of binding directly to the collection in that class you create smaller models that are more specific to the individual views.
When your main model receives a new item, it publishes an event, which is consumed by the smaller models who can inspect the new item and determine whether or not they should add that item to their internal collection (the one the individual views are bound to). If it doesn't "belong" to their view, they can simply ignore the event.
You could use similar event publishing for updates to items and such, although if you're binding to the actual items you probably don't need that.
Just implement the INotifyCollectionChanged Interface and the INotifyPropertyChanged and you ll get a Collection like the ObservableCollection.
But rember if you select a Item from your Collection (as example a ObservableCollection) and you change that item your other controls won t update. So if you have a class Person in your Collection and you change the name of one person the other controls won t get the new name of the person.
Inside the Person object you still have to implement the INotifyPropertyChanged Interface and raise the event when your name changes.
So what I want to tell you is: A Collection with the interface INotifyCollectionChanged will only tell the bound controls: There is a new Item, there has been a item removed or a items index changed BUT not if the item itself changes.
So you ll need a Collection that provides the points above and a Item contained by the collection that raises events if a property of it changes.
ObservableCollection is perfect here. You should find that a standard ItemsControl bound to an ObservableCollection will only update the controls of the items that have changed, not every item in the collection.
This is the reason ObservableCollection exists - the events that it raises specifically identify items that have changed, so that the UI can handle them sensibly.
I've tested this locally with a small WPF app and it works fine. Worth noting, though, that a virtualised items panel would probbaly appear to break this behaviour when it scrolls...
EDIT: rereading your question, you actually say "When a value in the collection is updated..." If your collection contains instances of a class, and you update properties on the class, you don't even need ObservableCollection for this to work - you just need the class to implement INotifyPropertyChanged.

Observable Collections and Linq for Silverlight on Windows Phone

I am binding to observable collections, but not sure how to filter and order them with linq. I need them to be observable, otherwise my bindings won't be notified of changes (right?). When you populate an observable collection, will it retain the order items were added to it?
I am not sure where to go from here.
For databinding, is there another type of collection that is observable, but that you can use linq on?
If you need to provide filtering and sorting on top of your list data, then you should probably use CollectionViewSource for binding rather than ObservableCollection. Geoff Hudik's post: WP7 In-App Searching, Filtering covers this.
ObservableCollection is the recommended collection to use when you know that the underlying data will change.
It will retain the order of items in which they were added
You can use other collections for databinding as well, Linq can be used on pretty much anything that implements IEnumerable.

Large Model Collections in MVVM

Whilst implementing my first MVVM application in WPF, I've been wondering about the pros and cons of wrapping Model collections in related ViewModel collections to use in the View.
In our system we are likely to have several potentially large collections e.g. Order Lines in an Order, and Stock Items which could be selected for an Order Line. At present these are looked up from SQL in the Data Access layer, and then SqlDataReaders are looped around to create a collection of Model Objects.
To then loop around the collection of Model objects when creating a collection of ViewModel objects seems like an unnecessary overhead. When there are large collections of Model objects would it be better to expose these directly on the View?
Thanks in advance for your help, Mark
Edit
While reading up on this subject I found this MSDN article from July this year (reviewed by Josh Smith no less) which gives a pretty balanced view of MVVM, and in the 'Collections' section said this:
Another problem with collections is
determining when or if to wrap each
Model instance in the collection
within a ViewModel instance. For
smaller collections, the ViewModel may
expose a new observable collection and
copy everything in the underlying
Model collection into the ViewModel
observable collection, wrapping each
Model item in the collection in a
corresponding ViewModel instance as it
goes. The ViewModel might need to
listen for collection-changed events
to transmit user changes back to the
underlying Model.
However, for very large collections
that will be exposed in some form of
virtualizing panel, the easiest and
most pragmatic approach is just to
expose the Model objects directly.
Thanks very much for the comments so far, trying to limit the amount of data passed into the ViewModel, or using paginated or other suitable controls would reduce problems I'm sure, but I wonder if there would there still be situations where it would be better to simply bind to a collection of Model objects within the ViewModel?
I guess that it would really depend on how you want to go about displaying the data. Afterall the ViewModel is primarily there to handle the data that the View requires.
Assuming that your data layer provides you with just the data collections you could always restrict the creation of elements within the ViewModel depending on those that you actually want to see.
For example you may have a Datagrid to display Order Items for a given Order.
Thus you could have a ViewModel Property AllOrderItems bound to the datagrid and yet its getter is as follows:
public List<OrderItems> AllOrderItems
{
get{return this.DataAccessLayer.GetOrderItems().Where(x=>x.OrderNumber==this.OrderNumber).toList();
}
Here the DataAccessLayer is a class that holds cache database data and interfaces to the database. If kept as a singleton then data duplication within it will be reduced.
You can adapt your ViewModel to do as much or as little filtering of data from the DataAccessLayer as requried. The collections can be Observable if requried and the DataAccessLayer can generate events for VMs to react to for cases of new data being added, removed, saved to the database.

Resources