tags:

views:

801

answers:

3

So lets say I have these classes:

public class Person
{
     public string Name { get; set; }
}
public class PersonCollection : ObservableCollection<Person> { }

And lets say I have a ListView whose ItemsSource is bound to a PersonCollection. Now lets say I have this code:

public void AddPeople()
{
     Person p = new Person() { Name = "Someone" };
     MyPersonCollection.Add(p);
     MyPersonCollection.Add(p);
     MyPersonCollection.Add(p);
}

So now I have a ListView with three items in which all three items are references to the SAME object. So now I select lets say items with index 0 and 2 in the ListView.

The ListView.SelectedItems property will say I have ONE item selected since both visually selected items are the SAME object.

So how can I get the visually selected items so I can remove the items at indices 0 and 2, without removing the item at index 1?

A: 

I think there's something wrong with your model! Whatever it is you are trying to achieve, I would try and find a more robust way of doing it.

amaca
What do you mean? Maybe this is the functionality I want. If you have a problem with my business logic then leave me alone.
Nick
+1  A: 

There are cases where this makes sense, adding people to a queue where appearing more than once is desirable for instance. For this case it seems like WPF is designed poorly. Is it possible to manually iterate between all items in the collection and check their selection state?

Michael
I haven't found anything like that so far, but that would be nice.
Nick
+2  A: 

In WinForms there is the ListBox.SelectedIndices property that would be useful here, but we don't have that in WPF, unfortunately...

You could iterate through the ListViewItems using ItemContainerGenerator.ContainerFromIndex, check ListViewItem.IsSelected and then remove them by index. However, this doesn't play well with virtualization because ContainerFromIndex could return null if you scroll away from the item and it gets virtualized.

The code would look something like this:

for(int ixPerson = myListView.Items.Count - 1; ixPerson >= 0; ixPerson--)
{
   ListViewItem personItem = myListView.ItemContainerGenerator.ContainerFromIndex(ixPerson);
   if (personItem.IsSelected)
   {
      mySourcePersonCollection.RemoveAt(ixPerson);
   }
}
Robert Macnee
Thanks that worked. I'm not quite sure what you mean about virtualization, but with the simple project we're doing, this will be quite enough for us. Thanks.
Nick
What I mean is that sometimes not every Person in the Items collection will have a ListViewItem due to virtualization. If you select the first Person in the ListView, then scroll down so it disappears, it's possible that calling ItemContainerGenerator.ContainerFromIndex(0) will return null.
Robert Macnee