How does SelectedListViewItemCollection implement

2019-08-01 05:30发布

问题:

I am trying to mimic the way a ListView and other controls handle SelectedItems collections. I have a class with a collection of items and each Item has a Selected property.

I want to mimic the smart behavior where an Item can change its own Selected property and upon doing so would raise a SelectedItemsChanged event in the parent class, and the SelectedItems collection should now reflect the change.

I am trying to implement a SelectedItemsCollection class which does not contain an inner list but instead checks the Selected state of each item in the main Items list. This way it doesn't need to be constantly updated and synchronized with the main list.

I was looking at the metadata for ListView.SelectedListViewItemCollection and it has the following declaration:

public class SelectedListViewItemCollection : IList, ICollection, IEnumerable

It does not implement Add, Remove, RemoveAt, etc. Isn't this against the rules of using the IList interface? I cannot compile without implementing them. Is this just a glitch in the way the metadata is created?

How should I go about emulating this functionality?

回答1:

Those methods are implemented explicitly.
For example disassembling the class with ILspy you can see that the Add() method is implemented as follows:

int IList.Add(object value)
{
    throw new NotSupportedException();
}

So, for instance if you have an instance of SelectedItemsCollection and you want to invoke the Add() method, you must cast the object to IList e.g. :

((IList)mySelectedItemsCollection).Add(...)

And yes, if you look at the metadata of the class through Visual Studio, the explicitly implemented methods are hidden.

About the Selected property... well the "trick" is that each item has a reference to the ListView it belongs to. When Selected property changes, the item calls SetSelectedState() method of the listView that raises a SelectedChanged event.

Also SelectedItemsCollection is created passing the ListView reference in the constructor, in this way the enumerations of the elements is actually performed on an inner member of ListView that is accessible from SelectedItemsCollection because it's a nested class.