I would like to know why according to this article and observable collection binds significantly faster(20 ms vs 1685ms, that's 800X faster) than a List<> collection in WPF. I looked at the internals of ObservableCollection and it uses a List as it's storage collection object(I used reflector and saw this in the constructor)
public Collection()
{
this.items = new List<T>();
}
So what's going on here?
The comparison in that article isn't between two simple binding operations, those measurements refer to a scenario in which you add a single item to a WPF ListBox that is already bound to either a List<T> or an ObservableCollection<T>.
As the author remarks:
...the CLR List<T> object
does not automatically raise a
collection changed event. In order to
get the ListBox to pick up the
changes, you would have to recreate
your list of employees and re-attach
it to the ItemsSource property of the
ListBox. While this solution works, it
introduces a huge performance impact.
Each time you reassign the ItemsSource
of ListBox to a new object, the
ListBox first throws away its previous
items and regenerates its entire list.
This explains the performance difference. Even though ObservableCollection<T> is backed by a List<T>, it implements the INotifyCollectionChanged interface, which renders all that extra processing unnecessary.
Related
I know the difference between a List and ObservableCollection from ObservableCollection<> vs. List<> but sources like Microsoft Xamarin.Forms docs say that
Because ItemsSource has been sent to an array, the content will not update as the underlying list or array changes. If you want the ListView to automatically update as items are added, removed and changed in the underlying list, you'll need to use an ObservableCollection. ObservableCollection is defined in System.Collections.ObjectModel and is just like List, except that it can notify ListView of any changes:
So what exactly would be different if I implemented a List as the ItemSource for my ListView in Xamarin.Forms in contrast to an ObservableCollection if data binding is done. Also, my List or OC consists of multiple levels of Lists or OCs of different objects.
Ex:
List<Data> = new List<Data>();
class Data{
public List<SomeOtherData> {get; set;}
}
With a regular List, when you update it (let us say by adding or removing something) your UI won't show that change even though in memory it is different. However, with an ObseravableCollection it will(exactly as the explanation states above).
That would be the biggest change really. If you implement it as a List you would have to manually update the list's ItemSource to honor whatever changes you have made
I have seen this post
Pros and Cons of using Observable Collection over IEnumerable
My Questions are for ComboBoxes/ListBoxes :
Is there a summary of what type of collections could be used in this kind of binding, I mean which collection type can be used for binding to an ItemsSource for ListBoxes/ComboBoxes Kind. Which interfaces does each of these collection has to implement in order to be able to be bound to an ItemsSource
Does any of these Collection offer certain disadvantage/advantages over the other in terms of rendering speed and async advantages, lets say with virtualization set to on? Or it does not matter once the ItemsSource has been set?
Enumerable
ReadOnlyCollection
ObservableCollection
...
I can't answer the speed comparison you ask for since the things listed are completely different things.
Let me explain that briefly:
IEnumerable is just an interface that provides you with a bunch of extension methods and iterator functionality. Notable collection classes that implement IEnumerable would be e.g. a Dictionary<>, or an ObservableCollection<> or a List<> for that matter.
ReadOnlyCollection (and I assume you don't mean IReadOnlyCollection) is a concrete implementation of IReadOnlyCollection that wraps around an existing class that implements the IList interface. You pass that into the constructor and it will give you read only access to the content of the collection.
ObservableCollection implements among other things IEnumerable and IList interfaces.
Assuming from the context of your question you ask if there are specific collections that you can bind to ComboBoxes or ListBoxes and alike that are preferable in terms of speed.
Let's look at the WPF ComboBox:
Its ItemsSource property asks for an IEnumerable, and as stated above you can use any concrete class that implements that interface. You mentioned ObservableCollection, that one is interesting because it implements the INotifyCollectionChanged interface.
It allows you to do the following: Once you have an ObservableCollection bound to the ItemsSource of the ComboBox if you e.g. Add() or Remove() items from it the ComboBox will get notified of the change and reflect that by adding, or removing items from the list of visible things in the dropdown. If you used e.g. a List<> instead that would not happen and you would have to rebind/reassign the ItemsSource again.
Let's get back to the speed question, we can break that down into several parts:
Construction of your collection:
A List will be cheaper to construct than an ObservableCollection
simply because of the fact that Observable collection has to
repeatedly raise the CollectionChanged event. So if you know that
you collection never changes and you can construct it completely
before you assign it to the ItemsSource you can use a List
instead.
Maintainance of the collection: As mentioned in 1. if the collection never changes and can be pre-constructed, don't use an ObservableCollection, use the List
instead
(Probably most interesting for you) Rendering of items: Depending on the Container (e.g. ListBox or ComboBox or any other for that matter) the largest amount of time will be spent
rendering the items unless the control virtualizes the items.
--What does #3 that mean?
Imagine you have a collection of 300 items and assign that to your container:
If it is not virtualized it will start rendering all 300 items which takes a while but you will likely only see a subset of them on the screen all the other ones are hidden and you have to move a scrollbar to get them into view.
If the control can virtualize it will render only the part you can see right now and maybe a couple extra directly adjacent and then when you scroll start rendering the ones that come into view on demand. This is significantly faster initially and maybe a little bit slower during scrolling.
Points 1 and 2 are likely very negligible for such small lists with 300 items, however you will likely want to look into #3. Even already for smaller datasets virtualization makes a huge difference because most of the time is spent rendering especially if you have complex/slow Styles or DataTemplates
This might not directly answer your question but will instead give you a hint into which direction to focus your efforts.
I have to make some programs in c# and in order to perform IO between programs i have to use, or property using INotifyPropertyChange(on a List<>) or ObservableCollection<>.
I'd like to know which one is the better to perform IO operation between c# programs.
Thank you for reading
Based on the criteria you list in the question & comments, you're best off with an ObservableCollection.
The INotifyPropertyChanged interface exists to tell you just that - a property changed. When you're talking about a list, the properties will be things like Count and Item[]. This means that, effectively, all you're actually being told is "the contents of the list have changed" but not any details as to what that change actually was. Without any such information, all your control can really do is redraw itself completely based on the current state of the collection.
With ObservableCollection, however, you get told when an item is added (and what that item was and where it was added) and when an item is removed (and what that item was and where it used to be). This is enough information for your UI control to only have to redraw what has actually changed, which is far more efficient than redrawing the entire thing. This is why ObservableCollection was invented - use it!
Take a note that ObservableCollection inherits both INotifyCollectionChanged, and INotifyPropertyChanged.
[SerializableAttribute]
public class ObservableCollection<T> : Collection<T>,
INotifyCollectionChanged, INotifyPropertyChanged
See documentation from link above:
In many cases the data that you work with is a collection of objects. For example, a common scenario in data binding is to use an ItemsControl such as a ListBox, ListView, or TreeView to display a collection of records.
You can enumerate over any collection that implements the IEnumerable interface. However, to set up dynamic bindings so that insertions or deletions in the collection update the UI automatically, the collection must implement the INotifyCollectionChanged interface. This interface exposes the CollectionChanged event, an event that should be raised whenever the underlying collection changes.
WPF provides the ObservableCollection class, which is a built-in implementation of a data collection that implements the INotifyCollectionChanged interface.
Before implementing your own collection, consider using ObservableCollection or one of the existing collection classes, such as List, Collection, and BindingList, among many others. If you have an advanced scenario and want to implement your own collection, consider using IList, which provides a non-generic collection of objects that can be individually accessed by index. Implementing IList provides the best performance with the data binding engine.
INotifyPropertyChanged is used to notify the UI when the bounded property value or collection is changed. Whereas ObservableCollection is used to notify the UI when the bound collection is modified(Ex adding or removing object from the collection) It cant notify the UI if the property value in one of the collection object is changed.
These two alternatives do not do the same thing. You are choosing between these two options:
a list property implementing INotifyPropertyChanged, where you throw the event every time the list is modified
a property of type ObservableCollection
With option 1, when you modify the list, an event is raised that says "the entire list has changed." If you have a UI element bound to this list (say, a ListBox), the entire element will have to be redrawn, because it has to assume that the entire list has been changed (that is: it may no longer be the same list!).
With option 2, you are raising specific events about individual items that were added or removed in the list. If you have a UI element bound to this list, it can respond by only modifying the UI that is relevant for these elements.
Consider the example where you remove an item from your list, and the list is bound to a WPF ListBox control. With option 1, the entire content of the list is re-created. With option 2, the removed item's control is removed but the rest of the list is left intact.
It should be clear from this example that the ObservableCollection - because it supports an event that is specific to what you are doing - will be more efficient in many cases. That said, unless you have a huge amount of data in the collection or a very complex UI, the performance gain will be negligible. Further, if you're making large modifications to your list, you may well find that it's faster to refresh the whole list.
Ultimately, no performance question can be answered accurately on StackOverflow without repeating the mantra: profile your code, and make a decision based on the results.
I am trying to bind a combobox in WPF like this,
<ComboBox Width="350" Margin="5" IsEditable="True" ItemsSource="{Binding ComboboxItems}" DisplayMemberPath="Name">
public List<ExpandoObject> ComboboxItems
{
get
{
return comboboxItems;
}
}
If I set the list like this in my view model,
comboboxItems.Clear();
foreach (ExpandoObject comboboxItem in repository.LoadComboboxItems())
{
comboboxItems.Add(comboboxItem);
}
NotifyPropertyChanged(this, x => x.ComboboxItems);
The NotifyPropertyChanged seems to work because a breakpoint on the ComboboxItems is hit, but then the combobox list does not update on the GUI. Snoop shows no binding errors or anything like that.
The first time the above list is updated it seems to work, so it can't be anything to do with using an ExpandoObject I don't think.
UPDATE:
Using an observable collection works, but I would like to know if I have a setter in a viewmodel like this which binds to a control on the GUI,
public string Database
{
get
{
return importData.Database;
}
set
{
importData.Database = value;
NotifyPropertyChanged(this, x => x.Database);
comboboxItems.Clear();
foreach (ExpandoObject comboboxItem in repository.LoadComboboxItems())
{
comboboxItems.Add(comboboxItem);
}
NotifyPropertyChanged(this, x => x.ComboboxItems);
}
}
Is that setter being run on a background thread? The reason I ask is will the setter block the GUI if it takes a while to load the items from the database?
This is where I went wrong the first time trying to use an ObservableCollection, by running the code in the setter on a background thread using BackgroundWorker. Updating the ObservableCollection caused an exception under those conditions.
I think it will work if you use an ObservableCollection<> instead of a List<>. Unless you use an ObservableCollection, xaml will not know that the contents of the list changed.
To answer the second part of your question, if you're trying to set the ObservableCollection using a BackgroundWorker directly, you will get an exception. One of the ways to get around the exception is to set the ObservableCollection using BeginInvoke
One thing to note: you don't need to call NotifyPropertyChanged(this, x => x.ComboboxItems); in your setter. This is because the property isn't changing; the property is a collection and the collection contents are changing. ObservableCollection will notify subscribers that the contents have changed.
Use ObservableCollection instead of the List.
Quoting MSDN:
You can enumerate over any collection that implements the IEnumerable
interface. However, to set up dynamic bindings so that insertions or
deletions in the collection update the UI automatically, the
collection must implement the INotifyCollectionChanged interface. This
interface exposes the CollectionChanged event, an event that should be
raised whenever the underlying collection changes.
WPF provides the ObservableCollection class, which is a built-in
implementation of a data collection that implements the
INotifyCollectionChanged interface.
Before implementing your own collection, consider using
ObservableCollection or one of the existing collection classes,
such as List, Collection, and BindingList, among many others.
If you have an advanced scenario and want to implement your own
collection, consider using IList, which provides a non-generic
collection of objects that can be individually accessed by index.
Implementing IList provides the best performance with the data binding
engine.
I have a render-heavy item template in an ItemsControl and want to minimize the recreation of child item templates when ItemsSource signals a change. I am wondering if, because ObservableCollection can tell WPF precisely what has changed (as opposed to just the whole list), if it is more efficient in rendering changes to the collection, or if WPF is smart enough to reuse previous item views if it detects the same item is still in the changed list.
Your suspicion is correct. WPF will not reuse previous views. If you replace the ItemsSource of an ItemsControl with a new List, it will create completely new views for each item in the list, even if the same items were in the old list.
You can test this yourself by putting a custom control in the ItemTemplate and adding a breakpoint or debug logging to its constructor. If you replace the ItemsSource with an identical list, you will see your control constructed once for each item in the list. On the other hand, when an item is added to an ObservableCollection you will only see it called once.
Note that the ItemsControl can reuse the container (such as ListBoxItem) if you are using a virtualizing panel and have container recycling enabled. See Link. It still can't reuse the contents of the container, however.
ObservableCollection only informs of addition and removal of objects - so perhaps not as precise as what you were expecting (if an object within the list changes, ObservableCollection will not fire off any notifications).