Finding all the ICollectionView's attached to a collection - wpf

We have multiple filters based on the same collection. i.e. we are displaying the same collection in a variety of ways. What i would like to be able to do is ask all of the CollectionViews to refresh when a property changes (as the collection view will only refilter if items get added/removed from the collection). Is there a way to find all the collectionViews associated with a given collection. Is there a two way link between the collection view and the collection, or a way to determine this link.
P.S. I dont think the answer is
ICollectionView coll = CollectionViewSource.GetDefaultView(Collection);
as this will give me the default view for the collection, not all of the ICollectionViews asscoiated with the Collection.

If your collection is an ObservableCollection, you can do a ResettableObservableCollection.
public class ResettableObservablecollection<T>: ObservableCollection<T>
{
//copy desired ctors
public void ForceReset()
{
OnCollectionChanged(new System.Collections.Specialized.NotifyCollectionChangedEventArgs(System.Collections.Specialized.NotifyCollectionChangedAction.Reset));
}
}
The ICollectionView that gets generated will be watching for that and refresh itself.

Related

Update the List view observable collection using MVVM

I have a usercontrol, with one list box and one list view control in it. For Listview i have bound the observablecollection of type TrafficManager class as shown below:
private static ObservableCollection<TrafficManager> _trafficCollection;
public ObservableCollection<TrafficManager> TrafficCollection
{
get { return _trafficCollection; }
set
{
_trafficCollection = value;
OnPropertyChanged("TrafficCollection");
}
}
I have bound this to itemsource of list view.
Now my requirement is on selection of the listbox item, i need to filter some items of the listview. For that i used a linq to get the desired rows from list view and added that to the list view collection. Before adding i did a listview Collection TrafficCollection.Clear() and then added to that collection.But now the issue is on selection of another item in list box i need the original listview contents again to carry out the filtering using the linq again. Here once the TrafficCollection.Clear() executes the original observable collection data vanishes. How do i maintain a backup of original observable collection data "TrafficCollection" of listview. Remember i have only one view. Is there anyway to do this? Please let me know.
you can use CollectionViewSource filtering, refer here
SO Link: Trigger Filter on CollectionViewSource
this will not clear original collection.

Two ListViews with different filters on the same data set

I have a ViewModel with some ObservableCollection _questions, which is loaded from DB when VM instance created. Also this list is used to collect data to save back to DB.
This Vm is used for a View1 and it displays the list in ListView with filtering by a property using CollectionViewSource.GetDefaultView(_questions).Filter = ...
Now I need to create View2 which will display same list but without filtering.
I can't bind it to the same ObservableCollection _questions because it has filter defined on CollectionViewSource, but I need to use it to keep SaveToDb code same.
Is it possible to have different filtering on the same data source for two different ListViews?
I have never enjoyed using CollectionViewSource. I would instead filter using a new property in my ViewModel that filters using Linq:
public IEnumerable<MyType> FilteredItems()
{
get
{
return MyCollection.Where(x => x.MyProperty == SomeValue).ToArray;
}
}
I would then bind ItemsSource to this property and use INotifyPropertyChanged event to notify UI of changes to the collection.
Its hard to tell if this fits your scenario well as there is not much information provided on what you need to achieve.

ObservableCollection + ICollectionView = ObservableCollectionView?

I have a View Model that exposes an ObservableCollection. Now I want to add grouping and therefore want to use a View class, like e.g. the ListCollectionView. But that is not a generic type. Also, if I construct a ListCollectionView from an ObservableCollection, then it is not updated when the ObservableCollection is.
Did someone implement an ObservableCollection-backed View-collection somewhere?
If not, is it possible to achieve this dynamism somehow by using XAML?
You don't need a specific implementation ; a CollectionView is just a view of a collection. You can get the default CollectionView for a collection using CollectionViewSource.GetDefaultView:
ObservableCollection<Something> collection = ...
ICollectionView view = CollectionViewSource.GetDefaultView(collection);

Implementing INotifyPropertyChanged with ObservableCollection

I want to pull data from a database to display into a ComboBox, and then allow users to select values from that ComboBox and add them into a ListBox (via add/remove buttons). Would I be able to get away with using an ObservableCollections to hold the database values to bind to the ComboBox, since it implements INotifyPropertyChanged (and CollectionChanged)? Sorry if this is a basic question, I starting learning WPF about a month ago.
I've read over the article (very well done) by Sacha Barber.
And I've looked over the MSDN page on ObservableCollection.
What would be the advantages/disadvantages of using an ObservableCollection vs a List (which I know does not implement INotifyPropertyChanged)?
Something you may want to note.
Don't confuse the ObservableCollection's implementation of INotifyPropertyChanged with the objects it contain's implementation.
If one of the properties of one of the objects within the ObservableCollection changes, the UI will not reflect it unless that object implements INotifyPropertyChanged as well. Do not expect the ObservableCollection to take care of this for you.
If the items in your combobox don't change (i.e. you don't add/remove/update items), then List will probably be OK for your needs (ObservableCollection will be too) if you manually notify that your List property changed when you affect it.
public List<X> MyList
{
get
{
...
}
set
{
if (... != value)
{
... = value;
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs("MyList"));
}
}
}
}
....
this.MyList = new List<X> { new X(...), new X(...) };
If you plan to add/remove or update items in your combobox (without creating a new MyList object, i.e. using this.MyList.Add(...)), then use ObservableCollection that is able to notify when the collection is updated (so it can update bindings).

How to keep a data-bound list reverse-sorted

I have a listbox bound to a collection. I would like the ListBox to always reverse the order of the items. This handler--hooked up to the control's load event--works for the initial load, but not thereafter. Ive tried using the SourceUpdated event but that doesnt seem to work.
How do I maintain a constant active sort?
MyList.Items.SortDescriptions.Add(New SortDescription("Content", ListSortDirection.Descending))
How is the collection stored that supplies the items for the ListBox? It should be a collection that supports INotifyCollectionChanged. The framework provides ObservableCollection<T> which you can use.
In the constructor of your ViewModel (or wherever the collection lives), you then get the DefaultView for adding the SortDescription. The CollectionView is like a layer on top of your collection, which you can use to sort, group, filter, etc. the items without actually affecting the underlying data source. The framework creates a default one for you. To get a reference to it, you can use code similar to the following:
var collectionView = CollectionViewSource.GetDefaultView(Widgets);
if(collectionView == null)
return;
collectionView.SortDescriptions.Add(new SortDescription("Content", ListSortDirection.Descending));
With that in place, you should be able to add items to the ObservableCollection<T> and the sort order will be maintained.
If your source collection is a List<T> or some other collection that doesn't implement INotifyCollectionChanged, there is no way WPF can detect when an item is added. You need to use a collection that implements INotifyCollectionChanged, like ObservableCollection<T>.
Also, the items in your collection need to implement INotifyCollectionChanged so that changes to the items are taken into account

Resources