4

I am experimenting with WPF and MVVM in our system. However iam having a problem with keeping things selected in lists using only MVVM ( without doing extra CollectionViews ). What i currently have is the list

ObservableCollection<ReservationCustomerList> Customers;

And then a property storing the selected Customer

ReservationCustomerList SelectedCustomer;

In my opinion now, when the list reloads (actually from another thread async), the selection should be able to be kept, however this does not happen.

Does someone have a nice clean way of achieving this ?

Morten Schmidt
  • 642
  • 8
  • 22

4 Answers4

4

The way we did it was that we did not replace the collection. We added/removed the entries and updated existing entries if required. This maintains the selection.

You can use LINQ methods like Except to identify items that are new or removed.

Muhammad Hasan Khan
  • 34,648
  • 16
  • 88
  • 131
  • This is offcause a solution, however it result in alot of extra code instead of simply replacing the list, this way you have to actually check every viewmodel and overwrite existing viewmodel and add/delete changes. Replacing the entire list is alot cleaner. – Morten Schmidt Oct 01 '11 at 17:50
  • I may be the best solution if multiple selection is possible. Would be awesome to have a code, though. – user1 Nov 18 '14 at 18:27
1

In case the reloaded list still contains the last selected item and you want that item to be selected, then you can raise the PropertyChange event for the property SelectedCustomer after your collection gets reloaded. Please make your sure your viewmodel class implements INotifyPropertyChanged interface.

Rohit Vats
  • 79,502
  • 12
  • 161
  • 185
  • This solution was actually working because i overwrote Equals. However doing this also resulted in other uninteded errors with WPF. – Morten Schmidt Oct 01 '11 at 17:48
  • As you can see here: http://www.lhotka.net/weblog/CommentView,guid,06f305de-ec32-4e20-b042-171b58f305ae.aspx WPF simply does not recognize that the model has changed when the new and the old viewmodel "Equals" each other. – Morten Schmidt Oct 01 '11 at 17:57
0

you can use the ICollectionView to select the entity you want.

ICollectionview view = (ICollectionView)CollectionViewSource.GetDefaultView(this.Customers);

view.MoveCurrentTo(SelectedCustomer);

in your Xaml the itemsControl must have IsSynchronizedWithCurrentItem=true

or if the ItemsControl has a SelectedItem property you can simply bind it to your SelectedCustomer Property.

blindmeis
  • 22,175
  • 7
  • 55
  • 74
0

When you "reload" your collection you basically replace all values in it with new values. Even those that look and feel identical are in fact new items. So how do you want to reference the same item in the list when it is gone? You could certainly use a hack where you determine the item that was selected by its properties and reselect it (i.e. do a LINQ search through the list and return the ID of the matching item, then reselect it). But that would certainly not be using best practices.

You should really only update your collection, that is remove invalid entried and add new entries. If you have a view connected to your collection all the sorting and selecting and whatnot will be done automagically behind the scenes again.

Edit:

        var tmp = this.listBox1.SelectedValue;
        this._customers.Clear();

        this._customers.Add(item1); this._customers.Add(item2);
        this._customers.Add(item3); this._customers.Add(item4);
        this.listBox1.SelectedValue = tmp;

in the method that does the reset/clear works for me. I.e. that is the code I put into the event handling method called when pressing the refresh button in my sample app. That way you dont even need to keep references to the customer objects as long as you make sure that whatever your ID is is consistent. Other things I have tried, like overwriting the collections ´ClearItems()´ method and overwriting ´Equals()´ and ´GetHashCode()´ didn't work - as I expected.

Sascha Hennig
  • 2,556
  • 1
  • 19
  • 22
  • This is offcause true, however us having overriden the Equals method means that two entities that have the same "ReservationID" are the same. However as written in the comment above the Equals method introduces other unintended error with WPF. – Morten Schmidt Oct 01 '11 at 17:53
  • When clearing your collection before recreating it, you basically reset the collection. Check out [this link](http://stackoverflow.com/questions/224155/when-clearing-an-observablecollection-there-are-no-items-in-e-olditems/2963340#2963340) which explains what happens when you .Clear() the an ObservableCollection on SO, especially: "To reiterate. **Reset doesn't mean clear**, it means _Your assumptions about the list are now invalid. Treat it as if it's an entirely new list_. Clear happens to be one instance of this, but there could well be others" Check out the edit above tho. – Sascha Hennig Oct 04 '11 at 09:10