I seem to be having a issue with updating a ListView with the data being changed in an ObservableCollection.
so I have a class called Items which inherits from the INotifyPropertyChanged class and implements the property change handler.
I then have an ObservableCollection of items which is then set to the source of a CollectionViewSource.
The List then binds to the CollectionViewSource.
When I change the data of a property in the ObservableCollection it will trigger the property change but not update the UI.
I've spent a while looking for solutions but most are for WPF which has a load of depreciated functions and from what I've read is that the WinRT ObservableCollection should just update when a property is changed.
I'm sure though that I am missing something otherwise it would be working for me.
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.
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.
I've implemented INotifyPropertyChanged and the update in my GUI works as supposed to. If the view model changes a value, the control in the window updates.
However, I also have a DataGrid control and the update in view model doesn't propagate to the GUI. If I change something in the the table and invoke store, the changed values are available for VM, including newly added rows.
I've looked at other classes, like INotifyCollectionChanged but got no wiser. Should I move over and use ObservableCollection or is there a more recommended approach?
IObservable is the way to go to notify the View of changes. As you have mentioned you models are already implenting INotifyPropertyChanged, so your in a good spot to take advantage of it.
I have an ObservableCollection<MyClass> named myCollection that should be binded to two CollectionViewSources (AllItems and SelectedItems).
AllItems's source property is binded to the myCollection. SelectedItems's source property should be bind to myCollection items which IsSelected == true.
public class MyClass : INotifyPropertyChanged
{
//fields and interface implementations
public string Name {//proper code};
public bool? IsSelected {//proper code};
}
// some where else in the MainWindow
AllItems.Source = myCollection;
SelectedItems.Source = myCollection.Where(input=>input.IsSelected==true);
Problem: Every thing is OK when the Window is loaded. But when the IsSelected value for some items in the myCollection is changed obviously it has no effect on the SelectedItems. So to overcome this problem I update the source property of the SelectedItems every time an IsSelected property is changed.
Question: How can I do these kind of binding so that there is no need to manually update the source property of the SelectedItems?
Thnaks.
First of all, you should unconditionally remove your manual filtering setup and replace it with something more appropriate. The choice of what to replace with depends mainly on what .NET version you are targeting.
If targeting .NET 4.5 then a simple solution is and instead enable live filtering on the collection view.
For earlier versions of .NET you will have to do some manual work no matter what, but it is better to just call Refresh on the collection view that re-bind your control. To do this, you should defer the filtering to the collection view itself by setting the Filter event handler from XAML.
After the changes in MyClass you should raise PropertyChanged Event.
If you already do this than you should look at your SelectedItems.Source in Debug mode. Maybe its the correct value already there but its not shown to you.
I mean if SelectedItems.Source belongs to some visible Elements - GUI - you should refresh it on the screen. Cause the other way the value is there but will not be shown till your Element on the Screen is repainted.
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.