Update the List view observable collection using MVVM - wpf

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.

Related

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.

cannot edit DataGrid cells if ItemsSource is bound to linq expression

I am getting exception "'EditItem' is not allowed for this view" when I try to edit an item in my grid view. This is because I bind the data grid to a LINQ query. My question is how to filter my original collection of items? Do I have to create another ObservableCollection (or whatever else implements IList) and copy my filtered items there?
EDIT: I know that duplicating data in to an ObservableCollection works. My question is: given the original collection, is there a memory efficient (constant memory complexity) way to filter and/or order the collection and make it editable inside the grid view?
private readonly ObservableCollection tasks = new ObservableCollection();
public IEnumerable OrderedTasks
{
get
{
return this.tasks.Where(t => !t.Complete);
}
}
<DataGrid ItemsSource="{Binding OrderedTasks}" />

ListView selection change doesn't remove an old item

I have a strange behavior with my WPF ListView Control.
ListViews ItemSource is Observable collection.the ItemSource is updated periodically.
When I'm selecting one of the item and then selecting other item and no item updated, everything is OK.
But when I'm selecting an item witch is updated while I'm standing on, then selecting other item, now I have two items selected instead of one.
When I'm looking with the debugger, I see the event args of SelectionChanged event. I see that added item is OK but no removed item.
Anyone knows what's the problem?
Thanks!
Edit:
My observable collection:
protected class CustomObservableCollection : ObservableCollection<T>
{
public void Refresh()
{
ListCollectionView lcv = (ListCollectionView)(CollectionViewSource.GetDefaultView(this));
lcv.Refresh();
}
}
The update method witch called when there is a change in some item:
public void RefreshItem(T domainObject)
{
foreach (T item in obsCollection) {
if (!DomainObjectComparer.Equals(domainObject, item)) continue;
DomainObjectCopier.CopyProperties(domainObject, item);
obsCollection.Refresh();
break;
}
}
It looks like your copier class makes two items in your collection equal (I think, inferring this from the limited amount of code above).
If two items or more are the same (equal) in a ListView, then selecting one will select all of them as an equality comparer is used in the selection logic.
Well, Apparently the problem was with the overridden GetHashCode() method of the ListView item object.
the hash code included all the fields in it's calculation. I remoed all the fields (properties) and now the overridden GetHashCode() is only calculating the hash based on item's ID. it solved the problem.
I also have Equals() method overridden.
If someone knows why it is related I will like to know.

problem binding ListBox on ObservableCollection<T>

I have a strange "problem". Could someone explain me why :
If I have in an ObservableCollection, twice (or more time) an item with the same value, then the selections of those values in the ListBox won't work properly ?
In fact, what the ListBox is doing when I click on an item(Even in single item selection) : It selects the first item from the ObservableCollection collection with a matching value. so in the case if multiple items with same value are in the collection, then only the first one will be selected !
Because objects you entered to collection have same references. you should create new instances in each case or override Equal function and write your logic for identifying items. WPF ListBox calls Object.Equal function to identify if the items are same.
Hope this helps
You need to create a new object to hold each object.
I.e.
MyCollection.Add(new MyContainer() { Data = myObject } );
This way the listbox will select the objects properly as it has unique containers.
This would be implicit if you were using ViewModels

Finding all the ICollectionView's attached to a collection

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.

Resources