What are some of the practical differences between using the CollectionViewSource.View.Filter property as opposed to the CollectionViewSource.Filter event? Are there situations where you would use one over the other or is it a matter of preference?
Cheers,
Berryl
EDIT:
I do see that the docs say "If your view object comes from a CollectionViewSource object, you apply filtering logic by setting an event handler for the Filter event." although nothing stops you from setting the property on the view, and it doesn't say why to do so.
The advantage I have found so far in setting the event on the CollectionViewSource is that you can implement all of your filtering logic in one event handler and then use View.Refresh (or View.DeferRefresh) to invoke it as the user changes filtering criteria.
Setting the Filter event in the CollectionViewSource would mean that the event is called even when there is no filtering needed which would make the process less efficient.
The official way of using the Filter event is by adding it on filtering and removing it later when the filter is cleared.
viewsource.Filter += viewsource_Filter;
Then:
viewsource.Filter -= viewsource_Filter; //how do you know how many events there are!?
If you use the event, you have to make sure that you are not adding the event each time the filter value changes, because apart from having redundant events lurking around (=app works harder for nothing) you will have to remove all the events in order to clear the filter.
Thus, there is an advantage in using the Filter property, because you can more easily clear the filter by setting the property to null.
viewsource.view.Filter = null;
Related
Take a custom realtime object "MyObject" one property of which is an IndexReference referring to a CollaborativeList "MyList". "MyObject" also has a collaborative field property "MyProps" into which I put a json string.
In order to detect changes to "MyProps" I tried the following:
MyObject.addEventListener(gapi.drive.realtime.EventType.OBJECT_CHANGED, dealWithChanges);
However, when I make any change to an object in "MyList", which shouldn't affect the IndexReference in any way, the OBJECT_CHANGED event is fired on "MyObject"
Is this by design? It makes the OBJECT_CHANGED event useless, effectively a "something has changed somewhere" event, but without it there appears no way to detect a change to "MyProps".
Object changed events bubble, so you can listen higher up the tree for anything that is happening lower.
To listen only for changes on collaborative fields within the particular custom object, you want a ValueChangedEvent
I am working on an application that uses WPF/C# with MVVM. I have one particular ObservableCollection<> which is bound to ListBox.
Scenario 1: When the application is running, I modify this ObservableCollection<> and ListBox is populated as expected.
Scenario 2: With new requirements I have to fill this ListBox by default with some init values. So I have added a method for initializing it in my ViewModel. I call this method in OnStartup() after initializing View & ViewModel. DataContext is also set properly. In this scenario values are updated in the ObservableCollection<>, Unfortunately they are not reflected in the ListBox.
Just to verify if anything is wrong with the OnStartup(), I added the same method call in a callback on ContentRendered from the View, instead of OnStartup() it did work fine.
So my question, When exactly MVVM guarantees that all the bindings are setup correctly?
Edit:
One more observation, if I pop a message/dialog ListBox is populated as expected. It calls ContentRendered callback. And then it populates correctly.
I am almost convinced that ContentRendered should be the function that guarantees the bindings.
I can't say with certainty that this is your issue, without seeing the change to the code, but it sounds like you may now have an initial value of null for the property to which you are binding.
If you subsequently set that property to an ObservableCollection<T>, there is no automatic change notification.
One option would be to raise a notification that the property value changed (from null to something), and then let the ObservableCollection<T> handle change notification from there.
The better solution would be to initialize the property with an empty ObservableCollection<T> from the get-go, then your initialization to default values will mean adding those values and change notification should happen as you expect.
You might get the same problem by starting with a non-null collection, then setting the property to a new instance of a collection, without raising a notification, but I'm not 100 percent certain of that.
If this is not your issue, then I'll be happy to take another look.
Using MVVM, my viewmodel is my WPF window's data context. In the viewmodel is an observablecollection that holds the items in a listbox. When I add items to the collection, the listbox updates as expected
As part of my generic undo function, the observablecollection can be replaced with an older version. This happens by passing the collection to a method by reference and changing the reference. Everything after the undo works correctly except for the listbox. This continues to show data from the old reference.
How can I either stop this from happening or change the reference that the datacontext uses so that my listbox is "undone" and then continues working?
You need to provide some change notification in order to trigger the UI to update which you won't get from reassigning a ref variable to another instance. To get the notification you can either Clear and re-fill the original ObservableCollection instance or fire a PropertyChanged event for the collection property's name after swapping the instances.
Using the MVVM pattern, properties are changed in the ViewModel, with setters raising the PropertyChanged event. The event is handled in the View (automatically by WPF) and bindings are refreshed.
In your case, the value is being changed without the setter being called, so the PropertyChanged event (if it exists) is not being raised.
One option might be to manually raise the PropertyChanged event from the undo code. This would allow you to keep your existing design (please note that INotifyPropertyChanged.PropertyChanged is different to ObservableCollection.CollectionChanged - do a bit of research if this is not clear).
The second option would be to handle the CollectionChanged event, and keep a record of ItemsAdded and ItemsRemoved.
Your undo mechanism can then re-add any items which were removed, or remove any items which were added. This might require a bit of design tweaking.
I would go with the second design, as I think the design rethink might be a good idea. If you are using MVVM, you should be using Commands, and if you are using Commands you can implement Undo/Redo functionality neatly by extending the Commands (remember that an action made by a user is usually a bit more than a value change).
I am using observable collections all around my applications. My problem is that when i use a popup window for editing those entities, my bound lists are getting changed when the user changes those corresponding fields in the window.
How could i simply freeze the observable changes norifications, and release them only when the entity is saved?
Thanks,
Oran
I think the issue is not with the collection, but with the entities themselves. ObservableCollection raises an event when an item is added or removed, not when a property of an item is changed. This part is handled by the INotifyPropertyChanged implemented by the item, so it's this notification you need to disable.
I suggest you have a look at the IEditableObject interface, which is designed for this kind of scenario. You can disable the notifications in the BeginEdit method, and reenable them in EndEdit and CancelEdit.
EDIT: Paul Stovell has a nice implementation of an IEditableObject wrapper here :
http://www.paulstovell.com/editable-object-adapter
You can use:
BoundPropertyOfViewModel = CollectionViewSource.GetDefaultView(AgentDeploymentDetail);
and bind to the view instead of binding directly to the ObservableCollection. This is the same object that allow you to filter/sort your output without touching the collection.
When you want to stop changes, use DeferRefresh(). When you are done, call Refresh().
WARNING
This will not pervent showing of changes in each item itself, only the list.
You could make a deep copy of the object you want to edit. This way, you can act on the copy while editing, without interfering with the original that remains in the list. Once you`re done editing, you can replace the original by the edited version or rollback.
All the anwers above are great. but i found a good and convinent prodedure to perform the desired in an efficient and clean way. It is based on performing a deep copy on a detached object, using Matthieu MEZIL entity cloner ( http://msmvps.com/blogs/matthieu/archive/2008/05/31/entity-cloner.aspx ).
For full details please check out the followings : Entity Framework Attach Exception After Clone
Thanks for all the great support...
I am binding a ListView a property that essentially wraps the Values collection (ICollection) on a generic dictionary.
When the values in the dictionary change, I call OnNotifyPropertyChanged(property). I don't see the updates on the screen, with no binding errors.
When I change the property getter to return the Linq extension dictionary.Values.ToList(), without changing the signature of the property (ICollection) it works with no problem.
Any reason why the Values collection bind and notify properly without projecting to an IList<>?
Calling OnNotifyPropertyChanged() isn't exactly correct in this case, since the collection is still the same, however the items in the collection have changed. I don't know exactly how the WPF binding code works, but it might do a quick check to see if the reference it is binding to has changed, and if not it won't update the UI.
The reason that ToList() works is because each time it is called, a new instance of List<T> is returned, so when OnNotifyPropertyChanged() is fired, WPF picks up on the change and updates all of its bindings.
I don't know if this is possible or not, but the ideal solution would be to use a collection for bindings that implements INotifyCollectionChanged. This will fire events that WPF monitors so that items can be added, removed, etc. from the UI as appropriate.