I'm refactoring a WPF application that before was using a ObservableCollection<T> as datasource with a ListCollectionView for performance purpose.
The main idea is that I've a ItemHolder which has a ObservableCollection<T> that contains all the data and each view of my application shows only a part of it (based on an IdParent).In this case ListCollectionView works fine since I set a filter on the ItemHolder.Items and I get the data.
I wish to execute a storyboard when a record is updated inside this collection (adding an item works since I see it on the GridView).
Is there a way I can get a storyboard applied when a item is changed? I've seen no SourceCollectionChanged (or something similar) as event of the ListCollectionView.
I have never worked with ListCollectionView before so I cannot tell you anything new. But I can suggest to create a custom control that inherits from ListCollectionView and then implement an CollectionChanged event to handle when an item is added to the custom control and trigger the animation from withing the user control.
Related
I used the List<Person> collection as the ItemsSource for the DataGrid control.
But it did not update the View if i remove the item from the List collection. I was struggling for a long time for the solution.
Then Instead of the List<Person> collection in my ViewModel. I changed this into ObservableCollection<Person> collection. Now it updates the view when ever there is a change in the collection.
I am not sure why it updates only for ObservableCollection<Person> ? Anyone ?
Well its in the name. A simple List doesn't tell the ui to update, in other words "the view can't observe the list". There is no weird magic behind Databinding. WPF and DataBinding needs the Data model to tell them "this is new" or "this is changed", you propably already saw INotifyPropertyChanged, INotifyCollectionChanged is the same but for collections, and the List<> doesn't implement it, ObservableCollection does.
Because List does not implement INotifyCollectionChanged
Because the update of a databinding is not a kind of magic, there are several requirements to make databinding working correctly. If you have a single property to bind on this property must be either a dependency property or its parent class must implement the INotifyPropertyChanged interface to notify the wpf binding system about changes of the property value.
For a collection there is a simelar mechanism: it must implement INotifyPropertyChanged to inform the wpf binding system about removed/moved/added items.
See here for more details: http://msdn.microsoft.com/en-us/library/system.collections.specialized.inotifycollectionchanged.aspx
ObservableCollection<T> fires change events every time you change the items in the collection. List<T> doesn't. That's the reason.
DataBinding is lazy. If you don't tell your view that something has changed, it won't bother updating. Under the hoods, WPF DataBinding registers for change notifications, so that your ViewModel can tell the view when it has changed. It does this with interfaces like INotifyPropertyChanged and INotifyCollectionChanged.
ObservableCollection<T> implements the interface INotifyCollectionChanged. This interface defines the event CollectionChanged, which your View basically attaches its own event handler to. That handler will update the view when the event is raised by the collection.
My class has a public List field. I want to detect when someone changes this collection. However, writing my own Add/Remove wrapper around this collection seems wasteful. Is there a way to get notifications about changes in collection with delegates or something like that?
Use ObservableCollection<T> instead
you may find reference here.
There already exists a collection you've described and it's called ObservableCollection.
It has CollectionChanged event, so just subscribe your event handler there and i'll get called every time item is added or removed from collection..
Use BindingList<T> instead. It offers a ListChanged event. It is also accepted as DataSource in many controls such as a Listbox or a Grid.
As mentioned in this answer the BindingList offers a lot more than ObservableCollection
If you want to change a list in a listbox and changes to that list be reflected to the UI, you can set a BindingList<> as datasource to the Listbox and then simply manipulate the list. The Listbox will handle the ListChanged event and will display changes without having to manually do it by your self.
If you are going to use it in Winforms you should go with BindingList and if you are going to use it on a WPF app then go with ObservableCollection.
For some reason when adding or remove items from the DataSource (a simple BindingList) the ComboBox updates accordingly but if I edit an item like this, it doesn't update automatically:
myBindingList[index].Name = "NewName";
myBindingList[index].Value = newValue;
In order to get it to update when I edit an item as opposed to creating or removing an item I have to do this after the change is made:
myComboBox.DataSource = null;
myComboBox.DataSource = myBindingList;
This fixes the problem but it seems like a rather messy solution. Also with large lists it may become slow (premature optimization I know) but still is there a way to force the ComboBox to update without completely re-assigning its DataSource?
Thanks for reading.
this is stated in the MSDN forums:
The IBindingList interface contains the ListChanged event where
controls like the combobox hook up into if the underlying datasource
assigned to it implements the said interface. your datasource must
raise the corresponding ListChanged with proper ListChangeEventArgs if
ever you add, remove, change, etc. your IBindingList implementor.
this way, whenever the underlying source you used to bind to your
combobox is changed, the corresponding UI control (combobox) is
refreshed.
you say you are using BindingList and in fact you do get the combobox to reflect add or remove items events. I think you should do the update of the items already inside your BindingList in another way because looks like the proper BindingList events are not firing.
you could either investigate into that or simply live with reset and reassign the DataSource, I don't think is too bad, you are in Statefull Windows Forms application not in SatetLess Webforms so you do have your objects there all the time :)
You need observable collections and IPropertyChange implementation:
ComboBox bound to a ObservableCollection does not update
I have created a Treeview in WPF MVVM (Project is using MVVM Light).
When I add a data to a DataTemplate of the Treeview, I want to reload the entire treeview. For this I am sending a Message from my data entry viewmodel to my treeview view model.
Though the message is recieved, the tree doesnt get refreshed. I called LoadChildren on each node again, and used RaisePropertyChanged as well but the data didnt get updated.
The TreeView is bound to a hierarchical collection in your ViewModel, and it has a property name, e.g. TreeViewData. Assuming your ViewModel implements INotifyPropertyChanged, simply call the PropertyChanged handler for property TreeViewData. This will completely refresh the TreeView.
My answer is based on the fact you are using Mvvm light, since you did not provide code I will just state the obvious and it might solve your issues.
Is your viewmodel implementing the ViewModelBase interface? (which implements INotifiedPropertyChanged)
I never used TreeViews but assuming it's using a collection as its datatemplate, you have to call RaisePropertyChanged on the collection whenever you add/remove an item and also whenever an item changes. Calling RaisePropertyChanged only in the "set" of the collection won't be enough.
I'm working on a project that controls multiple devices over USB and intercepts the WM_DEVICECHANGE events from Windows to manage currently connected devices and plugin modules using those devices. There exists a combobox on the main form that (should) display all available devices (the custom object) and be dynamically updated in the event of either device arrival or removal.
Now, every tutorial that I have read including some from here have directed me to set the DataSource property of the combobox to the List of objects that I have, and leave the DisplayMember/ValueMember property blank to display ToString() and to return the object as the value.
In some instances I have tried (such as post instantiating the List and populating it with sample/real objects) the combobox populates, however upon removal or arrival, the collection in the combobox does not update even when reassigning the List to the combobox's DataSource property after every device arrival/removal method.
EDIT: Oh right... the question...
How do I databind the collection of (custom objects returned as the values) dynamically such that it can handle sudden changes (additions/removals) to the list's contents?
EDIT 2: Sorry I didn't make this more clear, wasn't aware of how pervasive WPF has gotten, but this is a WinForms project.
Thanks in advance for any help you can provide. :)
even when reassigning the List to the
combobox's DataSource property after
every device arrival/removal method.
After reassigning, you need to call .DataBind() again.
If you're using .net 3.5 or above, you can use an ObservableCollection to have the list update automagically.
I'm not sure if you're using WinForms or WPF. I'm assuming WPF as nobody should start out on WinForms nowadays...
You need to change your List to an ObservableCollection<T>.
The WPF binding model relies heavily on a magic subsystem of fairies and warlocks (not mocking you, I'm actually serious). They have their own language for informing each other that something has changed between the DataContext and UI. These are primarily the DependencyObject/Dependency properties, INotifyPropertyChanged and INotifyCollectionChanged, and the ObservableCollection<T>.
By proper use of these totems, changes in your ViewModels/Models (the stuff you stick in the DataContext and/or bind to the DataSource) will be reflected on the UI.
I don't know about that ToString() bit. I always set the DisplayMember to the Property I want to display. I don't care about the ValueMember because the SelectedItem is my Object.
DataBind doesn't apply if this is a WinForms project, which it sounds like. (USB and stuff)
I don't do anything funky in my project when up update the data in a ComboBox, I just set the DataSource again.
EDIT:
You could try using a BindingList rather than a List also.
http://msdn.microsoft.com/en-us/library/ms132679.aspx