Sortable Object Collection - c#

I'm look for some direction.
I need a Sortable collection of objects which can also notify when items are added / removed from this collection as I'm binding it to a menu items as a list of windows open in my application.
Could someone please advise which would be a good collection type i.e. List<>, ObservableCollection et cetera and how I would go about sorting the said collection.
Many Thanks in advance.

This is sortable observable collection
And here is another implementation - I use this one in my project, works flawlessly (I just had to extend it so it implements also IList interface, so it can be used to define collections in XAML).

You could try and wrap your ObservableCollection in a CollectionView, notifications will be propagated and you can sort, filter and group items.
Note that the sorting does not modify the source collection which might be a problem if you need the changes to be permanent, then again only yesterday i used the class for the first time so don't know much about it, maybe you can apply the sorting to the source somehow.

Have you tried using System.Windows.Forms.BindingSource along with a System.Windows.Forms.BindingNavigator? These will do exactly what it sounds like you need- bind a collection of objects to a navigable menu.
As for sorting, you just have to get a list of the BindingSource's items, clear the BindingSource, do your sorting on the list, and add the sorted items to the BindingSource again.
See these links for helpful examples:
http://msdn.microsoft.com/en-us/library/b9y7cz6d.aspx
http://www.code-magazine.com/article.aspx?quickid=0507051&page=2
http://www.tech-archive.net/Archive/DotNet/microsoft.public.dotnet.languages.csharp/2008-09/msg01820.html
http://blogs.msdn.com/b/dchandnani/archive/2005/03/09/391308.aspx

Thanks for all the responses.
Was able to simplify things as I realised I only needed the collection to be sorted for display purposes when binding to the menu items.
I was therefore able to use the following code to sort my list of panel objects via menu item parent (miPanels) in this case. (PanelName being one of the properties of the object)
miPanels.Items.SortDescriptions.Add(new SortDescription("PanelName", ListSortDirection.Ascending));
Once again thanks for all the people who took the time to look and respond.

Related

Make Sortdescription also sort databound collection that is bound to listview wpf c#

I have a Listview that is Databound to an Observable Collection.
I have sorting implemented using SortingDirection ( applied it to The ListView and also tried applying it to a CollectionViewsource, after binding the CollectionViewSource also properly to the ListView )
The sorting of each column works without problems.
In my MainWindow.xaml.cs I change the positions of The Items in the Observable collection. To do this I have to clear the Sortingdirection applied to the ListViewSource, or it will resort the moving of files and The manuall up and down Movements will be overwritten by the sorting.
For this problem I need The sortdescription to Apply itself on the Bound Data, so I can remove it afterwards and still keep the sorted order.
Many people asked similar questions here, but answers always where "is it really important that the collection is sorted? Don´t you just want to apply it on the view?" My answer to this is yes, it is really important.
I would go with manually writing a sort for my collection, but it is databound and would fire events each time an object is changed during the Bubble Sort.
If anyone has a fix for this, please let me know.
Best regards.
To sort the list you extend observable collection:
Sorting ObservableCollection<T>
Then to suspend notifications. See Pause the Updates to DataGrid of bound ObservableCollection<T>
How to Avoid Firing ObservableCollection.CollectionChanged Multiple Times When Replacing All Elements Or Adding a Collection of Elements

Comparison of Collections for ListBox and ComboBoxes

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.

Performance, is it better to use Observable collection or INotifyPropertyChange?

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.

How do I keep the selection in ListBox when reloading ItemsSource

I am experimenting with WPF and MVVM in our system. However iam having a problem with keeping things selected in lists using only MVVM ( without doing extra CollectionViews ).
What i currently have is the list
ObservableCollection<ReservationCustomerList> Customers;
And then a property storing the selected Customer
ReservationCustomerList SelectedCustomer;
In my opinion now, when the list reloads (actually from another thread async), the selection should be able to be kept, however this does not happen.
Does someone have a nice clean way of achieving this ?
The way we did it was that we did not replace the collection. We added/removed the entries and updated existing entries if required. This maintains the selection.
You can use LINQ methods like Except to identify items that are new or removed.
In case the reloaded list still contains the last selected item and you want that item to be selected, then you can raise the PropertyChange event for the property SelectedCustomer after your collection gets reloaded.
Please make your sure your viewmodel class implements INotifyPropertyChanged interface.
you can use the ICollectionView to select the entity you want.
ICollectionview view = (ICollectionView)CollectionViewSource.GetDefaultView(this.Customers);
view.MoveCurrentTo(SelectedCustomer);
in your Xaml the itemsControl must have IsSynchronizedWithCurrentItem=true
or if the ItemsControl has a SelectedItem property you can simply bind it to your SelectedCustomer Property.
When you "reload" your collection you basically replace all values in it with new values. Even those that look and feel identical are in fact new items. So how do you want to reference the same item in the list when it is gone? You could certainly use a hack where you determine the item that was selected by its properties and reselect it (i.e. do a LINQ search through the list and return the ID of the matching item, then reselect it). But that would certainly not be using best practices.
You should really only update your collection, that is remove invalid entried and add new entries. If you have a view connected to your collection all the sorting and selecting and whatnot will be done automagically behind the scenes again.
Edit:
var tmp = this.listBox1.SelectedValue;
this._customers.Clear();
this._customers.Add(item1); this._customers.Add(item2);
this._customers.Add(item3); this._customers.Add(item4);
this.listBox1.SelectedValue = tmp;
in the method that does the reset/clear works for me. I.e. that is the code I put into the event handling method called when pressing the refresh button in my sample app. That way you dont even need to keep references to the customer objects as long as you make sure that whatever your ID is is consistent. Other things I have tried, like overwriting the collections ´ClearItems()´ method and overwriting ´Equals()´ and ´GetHashCode()´ didn't work - as I expected.

ObservableCollection of objects containing Lists

I am using an ObservableCollection for databinding as ItemsSource for DataGrid. Collection contains complex type objects. One of this type properties is a List of strings.
Just for now I see that when I update this List property from code nothing changes in the UI (the primary binding works fine). So, my question is: is it an expected behaviour? Maybe I should not use List as part of the type, but also use an ObservableCollection?
Update
Mode is set to OneWay.
Use a collection, instead of List, that implementes the interface INotifyCollectionChanged (like ObservableCollection). Then changes to the collection get populated to the ui.
Yes it is expected behaviour. The observable collection only notifies of changes to its own contents - that is add, delete, reorder.
What you are looking at is a change to an element in the observablecollection - if you want to see your changes to the class you put in, your element has to implement INotifyPropertyChanged.
So currently: If your list property on you complex object changes you won't see it, however if you change that too to be an observablecollection you could see changes to that collection in a sub-itemscontrol like a combobox - but not if you change the collection object to another one - so if you do not implement INotifyPropertyChanged you should set the collectionproperty before the binding is applied.
When you are updateding your list u have to call INotifyPropertyChange other wise UI wont get update the list result..
INotifyPropertyChange is the indication that here some changes occurred in the items source so update it.
This might help as well:
ObservableCollection that also monitors changes on the elements in collection

Categories

Resources