Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ObservableCollection.Contains() Doesn't Work Correctly

Tags:

c#

.net

vb.net

wpf

Consider the following:

class Bind
{
    public string x { get; set; }
    public string y { get; set; }
}
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        ObservableCollection<Bind> cX = new ObservableCollection<Bind>();
        ObservableCollection<Bind> cY = new ObservableCollection<Bind>();
        cX.Add(new Bind { x = "a", y = "1" });
        cX.Add(new Bind { x = "b", y = "2" });
        cY.Add(new Bind { x = "a", y = "1" });
        foreach (var i in cX)
        {
            if (!cY.Contains(i)) { lv.Items.Add(i); } //lv is a ListView control
        }
    }
}

Why does it add x = "a", y = "1" to the ListView?

If I change ObservableCollection to List or Collection, it does the same.

like image 936
Elmo Avatar asked Dec 31 '11 20:12

Elmo


People also ask

What is the difference between ObservableCollection and BindingList?

The practical difference is that BindingList is for WinForms, and ObservableCollection is for WPF. From a WPF perspective, BindingList isnt properly supported, and you would never really use it in a WPF project unless you really had to.

Does ObservableCollection implement INotifyPropertyChanged?

The ObservableCollection provides us with the CollectionChanged Event and implements INotifyPropertyChanged itself.

How do you use observable collection?

The ObservableCollection is already bound to the Listview. So all we need to do in the XAML file is to specify the binding member for each column. We can do that by the "DisplayMemberBinding" attribute and "Binding" markup extension.


1 Answers

The 'Contains' method uses the Equals on object, and this simply checks that the memory addresses are different.

Consider changing your class to this...

 class Bind : IEquatable<Bind> {
     public string x { get; set; }
     public string y { get; set; }
     public bool Equals(Bind other)
     {
         return x == other.x && y == other.y; 
     } 
}

Your loop will then visit the strongly typed Equals method in your class, and this will result in the behaviour you are after.

NOTE: the string class ALSO inherits from IEquatable of T and that is what allows the equality operator to operate on the content of the string rather than the address of the string.

like image 130
Gayot Fow Avatar answered Sep 25 '22 02:09

Gayot Fow