List or ObservableCollection? - wpf

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

Related

WPF bind property to array value using Prism MVVM [duplicate]

I have lots of entities with nested List<> in each.
For example, I have BaseEntity which has List<ColumnEntity>.
ColumnEntity class has List<Info> and so on.
We are working with a WPF UI, and we need to track all changes in every List of BaseEntity. It is implemented by instantiating a new ObservableCollection based on the needed list, and with binding to that ObservableCollection.
What are the pros and cons changing all these nested Lists to ObservableCollections? So we can track all changes in BaseEntity itself without reassigning each list of BaseEntity to modified bound ObservableCollection?
Assuming that methods specific to List are never used.
Interesting question, considering that both List and ObservableCollection implement IList<T> there isn't much of a difference there, ObservableCollection also implements INotifyCollectionChanged interface, which allows WPF to bind to it.
One of the main differences is that ObservableCollection does not have AddRange method, which might have some implications.
Also, I would not use ObservableCollection for places where I know I would not be binding to, for this reason, it is important to go over your design and make sure that you are taking the correct approach in separating layers of concern.
As far as the differences between Collection<T> and List<T> you can have a look here
Generic Lists vs Collection
It depends on exactly what you mean by this:
we need to track all changes in every List of BaseEntity
Would it be enough to track changes to objects already in the list? Or do you need to know when objects are removed from/are added to/change positions within the list?
If a list will contain the same items for their whole lifetime, but the individual objects within that list will change, then it's enough for just the objects to raise change notifications (typically through INotifyPropertyChanged) and List<T> is sufficient. But if the list will contain different objects from time to time, or if the order changes, then you should use ObservableCollection<T>.
So while the differences may be interesting (and a previous poster has already covered those), typically you won't have that much of a choice - either you need ObservableCollection<T> or you don't.
List represents a strongly typed list of objects that can be accessed by index. It provides methods to search, sort, and manipulate lists. The List class is the generic equivalent of the ArrayList class. It implements the IList generic interface using an array whose size is dynamically increased as required.
ObservableCollection is a generic dynamic data collection that uses an interface "INotifyCollectionChanged" to provide notifications when items get added, removed, or when the whole collection is refreshed.
Read more about it in this link: http://www.codeproject.com/Articles/42536/List-vs-ObservableCollection-vs-INotifyPropertyCha
One more important difference is you can access ObservableCollection only from thread on which it was created where as list can be accessed fromany thread.
I see no problem with that, other than a very marginal performance overhead.
Note that if you modify the internal Lists directly, you are not notified about changes. Also if the objects which are contained in the ObservableCollection are modified you are not notified. Notification occurs only, if elements are added, replaced, removed or moved.

Bool to Visibility Converter using a bool List [duplicate]

I have lots of entities with nested List<> in each.
For example, I have BaseEntity which has List<ColumnEntity>.
ColumnEntity class has List<Info> and so on.
We are working with a WPF UI, and we need to track all changes in every List of BaseEntity. It is implemented by instantiating a new ObservableCollection based on the needed list, and with binding to that ObservableCollection.
What are the pros and cons changing all these nested Lists to ObservableCollections? So we can track all changes in BaseEntity itself without reassigning each list of BaseEntity to modified bound ObservableCollection?
Assuming that methods specific to List are never used.
Interesting question, considering that both List and ObservableCollection implement IList<T> there isn't much of a difference there, ObservableCollection also implements INotifyCollectionChanged interface, which allows WPF to bind to it.
One of the main differences is that ObservableCollection does not have AddRange method, which might have some implications.
Also, I would not use ObservableCollection for places where I know I would not be binding to, for this reason, it is important to go over your design and make sure that you are taking the correct approach in separating layers of concern.
As far as the differences between Collection<T> and List<T> you can have a look here
Generic Lists vs Collection
It depends on exactly what you mean by this:
we need to track all changes in every List of BaseEntity
Would it be enough to track changes to objects already in the list? Or do you need to know when objects are removed from/are added to/change positions within the list?
If a list will contain the same items for their whole lifetime, but the individual objects within that list will change, then it's enough for just the objects to raise change notifications (typically through INotifyPropertyChanged) and List<T> is sufficient. But if the list will contain different objects from time to time, or if the order changes, then you should use ObservableCollection<T>.
So while the differences may be interesting (and a previous poster has already covered those), typically you won't have that much of a choice - either you need ObservableCollection<T> or you don't.
List represents a strongly typed list of objects that can be accessed by index. It provides methods to search, sort, and manipulate lists. The List class is the generic equivalent of the ArrayList class. It implements the IList generic interface using an array whose size is dynamically increased as required.
ObservableCollection is a generic dynamic data collection that uses an interface "INotifyCollectionChanged" to provide notifications when items get added, removed, or when the whole collection is refreshed.
Read more about it in this link: http://www.codeproject.com/Articles/42536/List-vs-ObservableCollection-vs-INotifyPropertyCha
One more important difference is you can access ObservableCollection only from thread on which it was created where as list can be accessed fromany thread.
I see no problem with that, other than a very marginal performance overhead.
Note that if you modify the internal Lists directly, you are not notified about changes. Also if the objects which are contained in the ObservableCollection are modified you are not notified. Notification occurs only, if elements are added, replaced, removed or moved.

How to reorder a ListBox's bound ItemsSource without access to the underlying collection?

I have created a control derived from a WPF ListBox that allows me to reorder the contents of the ListBox by dragging and dropping. I do this with the below code:
ListBox.Items.RemoveAt(sourceIndex);
ListBox.Items.Insert(targetIndex, droppedObject);
The problem shows up when I bind an ObservableCollection to this derived class's ItemsSource. When bound, an exception is thrown when I try to access the ListBox.Items and edit it. It instead wants me to edit the ObservableCollection instead. This makes sense to me, but I don't have access to this collection in the .cs file of my derived ListBox class. Since the implementation of my derived control should be generic, I shouldn't ever access a global ObservableCollection within it. I have attempted to access the ListBox's ItemsSource and try and do my updates to it, but I cannot seem to cast it into a list that allows me to easily edit it without knowing what the contents are. Is there an easy fix to this issue that I am missing?
but I cannot seem to cast it into a list that allows me to easily edit it without knowing what the contents are
You need to make sure that the type assigned to the ItemsSource property actually supports re-ordering of items, i.e. that it implements the IList interface. Otherwise you cannot use the RemoveAt and Insert methods.
Cast using the as operator:
var sourceCollection = ListBox.ItemsSource as IList;
if(sourceCollection != null)
{
sourceCollection.RemoveAt(sourceIndex);
sourceCollection.Insert(targetIndex, droppedObject);
}
If you get a null reference back, it means that the source collection doesn't implement the IList interface and you cannot move an item based on an index.
Yes, the correct way to do it is to actually reorder items in the underlying ItemsSource. I mean, you can coerce ListView to apply its own ordering (e.g. binding ItemsSource to a custom CollectionView instead), but things will get very messy when underlying collection changes. Personally, I'd avoid that route.
The proper answer would depend on why exactly do you want to order items and whether the ViewModel and Model layers should react to this reordering somehow (e.g. save the new items layout somewhere so it won't disappear after application is restarted). Normally, ViewModels are not expected to listen on changes to their ObservableCollections, but would rather accept 'MoveUp'/'MoveDown' commands from view and alter ObservableCollection accordingly.
On the other hand, if you're not creating an externally reusable library, and can guarantee that your ViewModels will not freak out if View starts to actually moving items around bound collection, its a relatively safe bet to just cast ItemsSource to non-generic IList interface and manipulate the items directly, as you suggested. Note that theoretically a bound collection may not implement IList, but in a real world application it almost certainly would.

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.

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

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

Resources