I know that an ArrayCollection is a wrapper over an Array, but what I wanted to know is when to choose one over the other? Will the over usage of ArrayCollections result in performance?
The main advantage of ArrayCollection is collectionChange event which allows to get advantage of data binding with it.
Some others are:
Possibility to filter or sort elements of collection without modifying or copying of underlying array.
Implementation of ICollectionView which allows to create a cursor and iterate collection with it.
Display of multiple arrays in a datagrid / etc (in this case, arrays are automatically converted to arrayCollections anyway)
If you don't need any of these advantages use simple Array.
Related
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.
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.
Say I have a main database class, TvShowDatabase, which contains a list of Shows. Each Show has a list of Episodes, each of which has a Length. The objects TvShowDatabase, Show and Episode all implement INotifyPropertyChanged.
I would like to compute and show TotalViewingPotential, a property of TvShowDatabase, which sums the Length of each Episode of each Show.
Moreover, let's say the user is looking at this structure in a tree style, and is able to edit the Length of any Show. When they do this, the TotalViewingPotential should update accordingly, and the results be seen on the screen.
My question: in WPF (and specifically, using Prism for MVVM), what is the best way to hook up the plumbing for these change notifications?
I've considered intercepting adds to each list (using ObservableCollection) and giving any new items a Parent. This, however, gets messy, and a top-down approach is preferable.
I've seen hyper-observable collections (http://www.codeproject.com/Tips/694370/How-to-Listen-to-Property-Chang), but I worry about event-subscription based memory leaks with this method, and it still requires a good bit of manual plumbing to raise the OnPropertyChanged(TotalViewingCollection) events where needed.
Is there a pattern for this?
The task, as you describe it, has a simple solution. You do not need to propagate changes along the collections.
TotalViewingPotential is a normal INotifyPropertyChanged property. Make it accessible from your Length properties.
In the setter of the Length property, compute the difference between the new and the old values, and increment the TotalViewingPotential by the difference.
That's all.
To speed up initial loading, in order not to generate notifications for all Lengths, you may set the values of the backing fields of Lengths, and compute and and set TotalViewingPotential based on the values from the DB.
I hit a performance obstacle when trying to instantiate a Collection by passing it directly the list of Models or by using Collection.reset. It takes about 6000ms to initialize it with 4800 Models with about 200 attributes each. This isn't that large so it's a bit surprising to start off, but going off of this, I tried to speed it up by setting Collection.models directly to the array of models, and setting Collection.length to the length.
The question, other than the initial sorting, what is the difference between these two methods and where are the resources being spent? I use reset to initialize the Collection so there is no need to remove event handlers on the Models or to clean anything up.
USE CASE:
Trying to display a table with infinite scrolling, where each row is a Model and the Collection is the collection of rows. Each row can have about 200 columns. This is a static table except for a single column which contains a checkbox. The Models aren't doing anything else.
There's a bit more to collections than their models and length.
When assigning directly, we're bypassing any other behaviors (sorting, existence-checking, etc) defined by the collection. Both reset and the constructor (which ends up delegating to reset) use the collection's heavy-ish set method to ensure new models are added consistent with the collection's designed behavior.
Direct assignment may be ok if the models will always be reset (i.e., not added or removed individually), but certain collection features may exhibit unexpected behaviors if the models are not set.
I have a problem. I have two observable collections with the same objects as content.
I grep one object from my datagrid with observablecollection.
datagrid.selecteditem as object
and want to delete it from the second observable collection. The line statement looks like
obscollection.remove(datagrid.selecteditem as object);
The objects are completly the same, but when I count obscollection the object isn't removed...
How can I solve this? Please no questions on why I need 2 collections with the same content ;)
When you say "the objects are completely the same", do you mean they are equivalent, or they are the same instance? My guess is that they are equivalent, but they are not actually the same object instance. The .remove() method of the ObservableCollection will be looking for reference equality, and therefore if it is not the same object instance, it won't find the object you're looking for (and therefore won't remove it).
I'd recommend looking at information about object equivalency, this article speaks to it, as does this answer (and there are many more out there if you do a search).
If the two collections have equivalent objects, but do not reference the same instance, then there are many simple solutions. One way would be to implement the IComparable interface, or use something like LINQ to find the equivalent object in the second collection and manually remove it.
Hope this helps.