ObservableCollection of objects containing Lists - c#

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

Related

When and where to use NotifyPropertyChanged

Could someone explain the use of notify property changed and in which cases should I be using it?
For example:
I have in my silverlight application the domain data source which loads data and the event LoadedData where I set to some lists (List) the content of the entities from the domain context and bind the lists to the girds.
Do I need to use NotyfiPropertyChanged on the Lists?
Thanks,
I think you are getting the concepts slightly confused here...
There are two relevant notification interfaces for use with XAML Binding technologies.
INotifyCollectionChanged - notifies listeners when the collection of items changes (as in add/remove/replace/reorder actions).
INotifyPropertyChanged - notifies listeners that the content of an object has changed (as in values have been set and itself and other properties have changed).
In your case, if you want to notify that the contents of the List have changed, you need to use an INotifyCollectionChanged enabled collection to do that (i.e. not List - typically ObservableCollection).
If you wanted to notify that an item within the List has changed then the object type contained in the List should implement INotifyPropertyChanged.

Removing an item from a WPF binding listbox

I have a WPF application with a ListBox (called listMyItems) which is successfully bound to a class of MyItems that I created. I have a List of MyItems called currentMyItems which is then assigned as ItemSource to the ListBox. It all works fine, if I add an item to the currentMyItems it pops up on the list, etc.
The problem occurs when I try to remove the selected item in the ListBox. This is the code that I use:
currentMyItems.Remove((MyItem)listMyItems.SelectedItem);
The item disappears from the ListBox but the next time I update it, it pops back up as it was never deleted. Any tips?
I think you may be confused about how data binding works. When you bind a property, you are telling WPF to go look somewhere else for the value of that property.
When you bind the ListBox.ItemsSource property to currentMyItems, you are telling WPF to go look at the currentMyItems list to find its list of items. If currentMyItems is an ObservableCollection instead of a List<T>, then the UI will automatically receive a notification to update the bound value when you add or remove an item from the collection.
Based on what you say in the question, it sounds like you you have two collections, one of which is bound, and the other which is used to recreate the first collection anytime a change occurs. All that is not needed.
Just create one ObservableCollection<MyItem>, bind it to the ListBox.ItemsSource property, and then add or remove items from that single collection. It should work as you would expect.
<ListBox x:Name="listMyItems" ItemsSource="{Binding MyItems}" />
and
MyItems.Add((MyItem)listMyItems.SelectedItem)
MyItems.Remove((MyItem)listMyItems.SelectedItem)
If you're interested, I also have some beginner articles on my blog for WPF users who are struggling to understand the DataContext. You may want to check out Understanding the change in mindset when switching from WinForms to WPF and What is this “DataContext” you speak of?
If you bound it correctly to an ObservableCollection and currentMyItems is that collection. Than it means that you must have reloaded currentMyItems in meantime.
Also consider binding the SelectedItem property of your ListView - your view model doesn't have to know about the view at all.
Your source collection must be modufy (inherit from IList or ICollection). If your source collection does not support this method of your interface Remove, you can't remove item from source.
So, when you want to remove item you must cast ItemsSource to IList or ICollection:
var source = listbox.ItemsSource as IList ?? listbox.ItemsSource as ICollection;
and then check:
if (source == null) return;
then:
listbox.SelectedItems.ForEach(source.Remove);
listbox.Items.Refresh();
Make the currentMyItems<MyItem> an ObservableColection<MyItem>. This way it will raise a property change whenever modified and the UI gets updated accordingly.
By using ObservableCollection you will automatically get updates on the UI.
You should use an ObservableCollection instead of List.
A good thing is to always use ObservableCollection instead of List when something to do with UI

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.

Binding List and UI controls, not updating on edit

I am binding a BindingList two way to a listbox. The Binding list contains a number of images which apparently only update the listbox if items are added or removed from the binding list. How can I make it so that the bindinglist also raises the listchanged event when an item is modified?
EDIT: I find the problem I am having is that a property of an object is not being changed, rather the base object.
BindingList<ImageSource>();
This wont work however if I did this:
BindingList<Image>();
And then set the binding path to Image.Source, it would update correctly and this is because a property of the Image has changed but in the case of the first example, only a direct item in the list has changed. So how may I get the same behaviour as the second example?
FINAL EDIT : It seems that using ObservableCollection instead of BindingList fixes this issue. I was under the impression that they were identical in notifying of changes in the collection. Full answer below
The list does raise that event but only if the underlying items provides the proper notifications via INotifyPropertyChanged.
The BindingList differs from ObservableCollection in that BindingList does not notify that its direct items are changed (except when items are added or removed from the collection). ObservableCollection however implements INotifyCollectionChanged and INotifyPropertyChanged interfaces. This means that any change to direct items of an ObservableCollection are reported to the UI.
If you are using bindings to direct items and need to update items and not properties of those items, it seems that you have to use ObservableCollection. Another solution would be to derive from BindingList and implement INotifyCollectionChanged.
I am not an expert but this is what i have gathered during the last hour, if anyone has anything to add or correct please let me know.

Is there a better way of updating a data grid then just adding and removing the datasource?

I have a List collection where UserPropDef is a custom class with a few public properties. I want to display the contents of this list in a DataGrid. So I set the DataGrid.DataSource property of my grid to the list and it displays the contents just as I want.
Now if I add or remove items from the list I want the DataGrid to update. I can't use a BindingList because this list needs to be serialized. I've tried calling the Update() and Refresh() methods of both the DataGrid, and the form and nothing seems to cause the DataGrid to refresh based on the current contents of the collection.
The only thing that works seems to be setting the DataSource property again. Yet when debugging my code I can see that after the collection has changed the DataSource property of the DataGrid is in fact still referencing the correct and updated collection.
Is there a better way to cause the DataGrid to refresh based on it's current DataSource?
My suggestion would be take what is behind door number 3:
Create a custom Serializable List that implements IBindingList (Or something that inherits from BindingList and fixes the Serializable issues. Check out Fixing BindingList... for ideas).

Categories

Resources