WPF MVVM - Refresh Treeview - c#

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.

Related

Why isn't this ListView binding to this list? [duplicate]

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.

Applying a Storyboard when a item changed using ListCollectionView

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.

Who should call the VIewModel in WPF/MVVM the logical unit or the view?

My question is of "What is the best practice?" type, in a very specific case:
I have a View that contains a listbox of checkboxes.
The listbox.ItemsSource is bound to a collection in the ViewModel (List of Person). And each checkbox.IsChecked is bound to Person.IsSelected.
The check/uncheck of a checkbox activates a 'Refresh' method in the ViewModel, that may or may not re-set the Person.IsChecked of all Persons. That, of course, should notify the UI that Person.IsChecked (might have) has changed.
My question is: Who should be responsible of calling ViewMode.Refresh? Should the UI call the method through an event or Command maybe? Or should the ViewModel subscribe to a proper event in Person.
If the UI is bound to IsChecked, nothing needs to notify it. Or, rather, WPF itself notifies it. That is one of the attractive qualities of MVVM. The view model can simply update its state according to its own set of rules, and the view automatically receives those changes via bindings.
depending on what you mean by "call"
here are the answers
if you mean create:
other ViewModel
anything that's not a View or an Model(because non of them should know your VM)
if you talking about executing a Method:
self execute (e.g. after PropertyChanged, Command, ...)
other ViewModel
anything that's not a View or an Model(because non of them should know your VM)
also important in your case:
you say your list is bounded to Collection
and here you could get some trouble because your View changed the Person.IsSelected which should raise a PropertyChanged for your IsSelected.
Now it will stuck because ObservableCollection doesn't get notified if your Item Property Changed that is a known issue. To fix this problem you need to wire up your INotifyPropertyChanged event to the CollectionChanged event from your ObservableCollection. So it can bubble up to your VM and it can execute his Refresh()
Here you can see an example how you could do it.
I think you have to ask yourself, what is the "refresh" in response to?
If it's in response to the check box physically being clicked, then it's the view's responsibility to call it.
If it's in response to the person being selected, the viewmodel should be watching its own collection for changes to IsSelected.
I agree with MehaJain that the latter is harder to set up, but the alternative breaks up the responsibility of a single unit of work between the layers, meaning that the logic will need to be duplicated in any other function that causes IsSelected to be changed. This includes other views binding to the same information, other commands (say you have a button for running a filter that selects certain people), and tests.
I would prefer to Refresh the View Model through the event or Command.
Because subscribing the collection members is tricky.
Let say you want to use the second approach: Subscribing to the Person class changed event.
Then it can have following disadvantages:
In the constructor of your view model you have to subscribe each "Person" member of your list.
In view model whenever collection gets modified then you have to subscribe/unsubscribe the added/deleted members of that list.
While disposing your view model, you have to unsubscribe the subscribed changed events.
So, this is an over head if you go for subscribing the change event of Person class.

Updating a property in a ObservableCollection WinRT

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.

WPF MVVM accessing item bound to child view in Command implementation

Hi I implemented something I asked in a thread here WPF MVVM Master detail view with a datagrid and a TabControl
It is a master details view with a datagrid as master and TabControl as child view. The SelectedItem of the grid is bound to the ItemsSource of the TabControl.
How can I access the Item bound to the TabControl in the Command written in the viewmodel? Basically I want to add new item in the bound collection (to child). But the bound item is the selectedItem of the datagrid - how do I find which one it is.
It would help to have some detail about the command you're trying to get to work, but you should be able to bind the CommandParameter on whatever control you're using to the same DataGrid.SelectedItem property that you're using for the TabControl's ItemsSource. That CommandParameter should then be available to you as a parameter into your command handler (might look different depending on what ICommand implementation you're using - DelegateCommand, RelayCommand, etc).
Do not wire the controls directly together but introduce some kind of a proxy property in your viewmodel that both controls bind to. One of them with Mode=TwoWay.
You can use CollectionViewSource.GetDefaultView() to return the ICollectionView that the TabControl is bound to. If you set IsSynchronizedWithCurrentItem to true on the TabControl then the ICollectionView's Current property will be what you can pass in to your command
You need a property in your ViewModel called SelectedCause . Bind the SelectedItem property for your DataGrid to this SelectedCause Property. Then, instead of binding the TabControl to SelectedItem.Solutions, bind that to SelectCause.Solutions . It's better to do it this way precisely because of the problem you are having. You need a property in your ViewModel that represents the currently selected Cause. The ViewModel is meant to be a representation of the state of the View. The selected item in the DataGrid is part of that state, so you should have a SelectedCause property in your ViewModel.

Categories