1

I've seen answers mentioning something compact like this:here

List<T> withDupes = LoadSomeData();
List<T> noDupes = withDupes.Distinct().ToList();

So I tried the following (syntax)

List<InfoControl> withDupes = (List<InfoControl>)listBox1.ItemsSource;
listBox1.ItemsSource = withDupes.Distinct().ToList();

but withDupes is null ? Perhaps I am retrieving the wrong data list. I added InfoControls one at a time.

Is there something else I should be implementing in InfoControl class? (Equal,hashCode)?

Thanks Addendum 1: [ignore I should not be translating from Java :) ] Also have (translated from a Java example, not sure it's 100% correct) declared in the InfoControl class..

public Boolean Equals(Object obj) 
{ if (obj == this) { return true; } 
if (!(obj is InfoControl)) { return false; } 

InfoControl other = (InfoControl)obj; 
return this.URL.Equals(other.URL); } 

public int hashCode() 
{ return this.URLFld.Content.GetHashCode(); } 

Addendum 2: When I try to use override based on the msdn link custom type example it says it is sealed :) It does not seem distinct is stepping thru GetHashCode() and I am still getting the same listbox.items.count after distinct.

bool IEquatable<InfoControl>.Equals(InfoControl other)
{
if (Object.ReferenceEquals(other, null)) return false;
if (Object.ReferenceEquals(this, other)) return true;
return URL.Equals(other.URL);
}

public int GetHashCode(InfoControl obj)
{
     return obj.URL.GetHashCode();
}

Addendum 3: When I try override VS2010 says it is sealed? "cannot override inherited member 'System.Windows.DependencyObject.GetHashCode()' because it is sealed" what am I doing wrong?

  public override int GetHashCode()
    {
        return URL.GetHashCode();
    }

   public string URL
    {
        get { return this.URLFld.Content.ToString() ; }
        set
        {
            this.URLFld.Content = value;
        }
    }

. Addendum 4:

   public partial class InfoControl : UserControl
         , IEquatable<YouTubeInfoControl>

    {

        private string URL_;
        public string URL
        {
            get { return URL_; }
            set
            {
                URL_ = value;
            }
        }

        bool IEquatable<YouTubeInfoControl>.Equals(YouTubeInfoControl other)
        {

            if (Object.ReferenceEquals(other, null)) return false;


            if (Object.ReferenceEquals(this, other)) return true;

            return URL == other.URL;
        }

        public override int GetHashCode()
        {
            return URL.GetHashCode();
        }

    }
Community
  • 1
  • 1
Marie
  • 39
  • 1
  • 6
  • I tested it just now and if the `override` keyword is missing it fails. Also the method needs to return the same HashCode for euqal objects as you might have read. But the method itself looks fine. – H.B. May 04 '11 at 23:29

2 Answers2

1

A ListBox's items can either be set via ListBox.Items or ListBox.ItemsSource, if you add items using listBox1.Items.Add this does not affect the ItemsSource which will stay null. In this case you should get your initial list from listBox1.Items.

H.B.
  • 166,899
  • 29
  • 327
  • 400
  • Do you mean get them from listBox1.Items one at a time or is there a method to retrieve the List<> all at once w/o a loop? Thankx – Marie May 04 '11 at 20:03
  • Something like `listBox1.Items.SourceCollection.Cast().ToList()` will probably do. – H.B. May 04 '11 at 20:16
  • Thanks, I am learning something new. I see also that I have to Clear the listbox in order to assign to ItemsSource and once I do that (binding) it complains my about .Add so it's either the binding way or the highway :) I would have to change all my list edits to target my application level List Thank you you've answered enough. – Marie May 04 '11 at 20:33
  • Still the following is not removing duplicates from UI perhaps I am missing a refresh after setting ItemsSource? `List withDupes = listBox1.Items.SourceCollection.Cast().ToList(); listBox1.Items.Clear(); listBox1.ItemsSource = withDupes.Distinct().ToList();` I can't get code markup to work, See addendum bottom of main post. Thanks – Marie May 04 '11 at 21:09
  • [`Distinct`](http://msdn.microsoft.com/en-us/library/system.linq.enumerable.distinct.aspx) uses the the default equality comparison, for reference-types that will always return false unless both reference the same object. Did you add the same object to the list multiple times? If not there will no duplicates by default. You can provide your own comparer in an overload though, or implement `IEqualityComparer` in your object class. – H.B. May 04 '11 at 21:15
  • The source XML results from merges of other XMLs w/o dup checks. I wanted a post-process remove dups. I thought from my readings that Distinct will be using the Equals() I show in the post? – Marie May 04 '11 at 21:57
  • That method needs to override the default Equals as far as i know. You could use a test-list and see how it behaves if you change various things. – H.B. May 04 '11 at 21:59
  • How do I go about implementing the comparer I tried `code` #region IEqualityComparer Members public bool Equals(InfoControl x, InfoControl y) { return x.URL.Equals( y.URL ) ; } public int GetHashCode(InfoControl obj) { return obj.URL.GetHashCode(); } #endregion`code` string URL is my key. how to markup code in comments – Marie May 04 '11 at 22:00
  • Check the msdn reference of `Distinct` that i linked to for an example of how to implement the interface. Then you just need to insert your own logic at the right place. – H.B. May 04 '11 at 22:15
  • Thanks for the link, did not notice it at first. Note the link mentions IEquatable not IEqualityComparer? Also VS2010 only insert the stub for .Equal as follows but nothing for GetHashCode()? When I try to use override based on the msdn link custom type example it says it is sealed :) It does not seem distinct is stepping thru GetHashCode() and I am still getting the same listbox.items.count after distinct. (code in next comment) – Marie May 04 '11 at 22:58
  • bool IEquatable.Equals(InfoControl other) { if (Object.ReferenceEquals(other, null)) return false; if (Object.ReferenceEquals(this, other)) return true; return URL.Equals(other.URL); } public int GetHashCode(InfoControl obj) { return obj.URL.GetHashCode(); } – Marie May 04 '11 at 23:00
  • You need to specify the hash-code method as `override`, otherwise it might not get called. – H.B. May 04 '11 at 23:19
  • When I try override it says "no suitable method found to override" public override int GetHashCode(InfoControl obj) { return obj.URL.GetHashCode(); } – Marie May 04 '11 at 23:45
  • The `GetHashCode()` you should override does not take a parameter, it works with its own instance variables, so the body is just `Url.GetHashCode();`. – H.B. May 05 '11 at 00:28
  • So if I try the following VS2010 says it is sealed? "cannot override inherited member 'System.Windows.DependencyObject.GetHashCode()' because it is sealed" public override int GetHashCode() { return URL.GetHashCode(); } – Marie May 05 '11 at 01:13
  • Why the hell is your data-object a DependencyObject? – H.B. May 05 '11 at 04:43
  • I have no idea, see Addendum 4 for the smallest InfoControl class declare which still complains about "cannot override inherited member 'System.Windows.DependencyObject.GetHashCode()' because it is sealed" – Marie May 05 '11 at 06:45
  • One should not have collections of UserControls and compare them, use [**Data Templating**](http://msdn.microsoft.com/en-us/library/ms742521.aspx) to create those on the fly from your data, your list should contain data only (and the classes should not inherit from DependencyObject) – H.B. May 05 '11 at 08:55
0

If you're adding the InfoControl objects one at a time, the ItemSource of the listBox will remain set to NULL. You're better off binding a List to the listbox which will allow you to get the data back off of the ItemSource property later

Dav Evans
  • 4,031
  • 7
  • 41
  • 60
  • Even though I am not using binding because my brain struggles with MVVM :), is there still a syntax on other members to retrieve the List in one step? Thank you. – Marie May 04 '11 at 20:12
  • Actually regarding MVVM I have not stumbled yet on a tutorial showing in *simple* examples patterns how the old (non-MVVM) versus MVVM approaches contrast, perhaps the closest blog was John Papas. I have failed to build the mental model yet and that's perhaps why I have skipped the (Binding) step to build from XML into a list first. All future edits including sourcing from UI like DragAndDrop should target the data structure, I presume. – Marie May 04 '11 at 20:23