Search code examples
c#.netwpfvb.netsilverlight

WPF ListView confusing the SelectedItem with equal items


A ListView (or ListBox) with following properties:

  <ListView SelectionMode="Single">
     <sys:String>James</sys:String>
     <sys:String>Claude</sys:String>
     <sys:String>Justing</sys:String>
     <sys:String>James</sys:String>
  </ListView>

will result in selecting two items simultaneously if I click on "James", even though I chose SelectionMode="Single". It's even the same behaviour when I use a helper class with a string-property to display in the ListView. It seems like the ListView is evaluating the Items and selecting those which are Equal() rather than ReferenceEqual(). Is there a way to change this behaviour so that the ListView treats every item individually?


Solution

  • The problem really is Equals() versus ReferenceEquals().

    It's even the same behaviour when I use a helper class with a string-property to display in the ListView.

    Not quite. You get the same behavior if you use an anonymous helper class.

    Why doesn't wrapping an anonymous type around the string fix the problem? As described here, when you create an anonymous type, the compiler creates a generic Equals() method that returns true if the objects are of the same (anonymous) type and their properties have the same values.

    The solution is to implement a real (non-anonymous) class - it can be as simple as this:

    public class Item
    {
        public string Display { get; set; }
    }
    

    Object.Equals() does a reference comparison, so as long as you don't override it, you'll get the behavior you would expect.

    I suspect that the design of the control assumes that you're not going using it to display lists containing two equal items.

    As to why it uses Equals and not ReferenceEquals, I suspect that the underlying design choice has to do with the fact that controls have to be able to display value types. ReferenceEquals boxes value types, with the result that ReferenceEquals(1,1) returns false.