Solved

Get uniqe property list from ObservableCollection using Linq

Posted on 2011-02-26
25
2,720 Views
Last Modified: 2013-11-11
I have a object model that has ID, Name and Category properties

I have another object model that is an ObservableCollection of my first model

I want to get all the unique categories from my collection using Linq, but I am not sure how to do it...

I was using something like:

            var sel = (from i in items
                      select new
                      {
                          i.Category
                      }).Distinct();

but I am getting a null value from it (there are 1000 test records in the collection all with categories)


New to Linq, so I am not sure what I am doing wrong.
0
Comment
Question by:S7up1d
  • 11
  • 9
  • 3
  • +1
25 Comments
 
LVL 42

Expert Comment

by:sedgwick
ID: 34990487
what is the type of Category?
0
 

Author Comment

by:S7up1d
ID: 34990517
Sorry, should have included that....

Category is string
0
 
LVL 42

Expert Comment

by:sedgwick
ID: 34990672
the linq expression is correct.
if u remove the Disticnt() call, do u get all categories?
0
DevOps Toolchain Recommendations

Read this Gartner Research Note and discover how your IT organization can automate and optimize DevOps processes using a toolchain architecture.

 

Author Comment

by:S7up1d
ID: 34990940
I get nothing...  I get this error:

System.Collections.Generic.IEnumerator<TSource>.Current = Could not evaluate expression
0
 
LVL 42

Expert Comment

by:sedgwick
ID: 34990946
ok, so we need to go one step back and examine the items collection.
if you debug the code and "Watch" the items collection, can u view its items?
how do u fill the items collection?
0
 
LVL 62

Assisted Solution

by:Fernando Soto
Fernando Soto earned 500 total points
ID: 34991826
Hi S7up1d;

Code like this works.

ObservableCollection<MyObjectModel> MyObservable = new ObservableCollection<MyObjectModel>( );
// Initialize the ObservableCollection MyObservable here
// ...

// Linq query using MyObservable collection of MyObjectModel
var sel = (from i in MyObservable
           select new 
           {
               i.Category
           }).Distinct();

// Iterate through the collection
foreach( var s in sel )
{
    Console.WriteLine( s.Category );
}

// ...

public class MyObjectModel
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Category { get; set; }
}

Open in new window


Note in my code I am using the ObservableCollection of type MyObjectModel in the query. Is your code is items variable of  ObservableCollection of type MyObjectModel? If it is can you please post your code as I did so that we can see the whole picture.

Thank
Fernando
0
 

Author Comment

by:S7up1d
ID: 34992285
so, the code I had was working, I was misinterpreting the errors and not iterating through the collection to check it.  A bit hairbrained on my part.

The last part of this is that I cannot get it to return the observable collection of properties as an observable collection... I get invalid cast exception when I use:


                    categories = (ObservableCollection<string>)(  from i in items
                                                                  select new
                                                                  {
                                                                    i.Category
                                                                  }).Distinct();


0
 
LVL 62

Assisted Solution

by:Fernando Soto
Fernando Soto earned 500 total points
ID: 34992365
Hi S7up1d;

There is no direct conversion to an ObservableCollection from Linq. So this is what you need to do:

IEnumerable<string> sel = 
    ( from i in MyObservable
      select 
          i.Category
    ).Distinct( );

ObservableCollection<string> categories = new ObservableCollection<string>(sel);

Open in new window


That should give you an ObservableCollection of Strings.

Fernando
0
 

Assisted Solution

by:S7up1d
S7up1d earned 0 total points
ID: 34992469
I tried this:

                   IEnumerable<string> distinctCategories = (from i in items
                                                                  select
                                                                    i.Category
                                                            ).Distinct();

                    categories = new ObservableCollection<string>(distinctCategories);  



I get the IEnumerable<string> but when I try to assign the categories to a new ObservableCollection<string> it will not go as there is no constuctor that accepts a single argument.  

Is there another way to convert this or do I have to just use the IEnumerable?
0
 
LVL 62

Expert Comment

by:Fernando Soto
ID: 34992495
What data type is categories?
0
 
LVL 62

Expert Comment

by:Fernando Soto
ID: 34992501
BTW I just test the code I posted to you and it does work on my system.
0
 

Author Comment

by:S7up1d
ID: 34992596
ObservableCollection<string> categories;

0
 
LVL 62

Expert Comment

by:Fernando Soto
ID: 34992668
Hi S7up1d;

Can you please post all the pertinent code copied from your project and past here so I can have a look. As I stated I have tested this code and it does work.

The three overloaded constructors for the ObservableCollection<T> from Microsoft Documentation:
ObservableCollection<T>()
ObservableCollection<T>(IEnumerable<T>)
ObservableCollection<T>(List<T>)               // The one used in the example above

Open in new window


Fernando
0
 
LVL 62

Expert Comment

by:Fernando Soto
ID: 34992681
What version of .Net and C# are you using?
0
 
LVL 62

Expert Comment

by:Fernando Soto
ID: 34992708
Hi S7up1d;

It appears that in .Net version 3.5 the ObservableCollection only had the default constructor and the reason for the error you are getting. Try this version of the code to get what you need.

IEnumerable<string> sel = 
    ( from i in MyObservable
      select 
          i.Category
    ).Distinct( );

ObservableCollection<string> categories = new ObservableCollection<string>();

foreach( string c in sel )
{
    categories.Add( c );
}

Open in new window


Fernando
0
 
LVL 62

Expert Comment

by:Fernando Soto
ID: 34999200
Has my last post corrected the issue?
0
 
LVL 12

Expert Comment

by:kumar754
ID: 35021217
well, I thought .NET 3.5 also has the same 3 constructors asin .NET 4.0

Reference:
http://msdn.microsoft.com/en-us/library/ms658737(v=VS.90).aspx

check your using/imports namespace

using System.Collections.ObjectModel;


Also, if you are using .net 3.0, then try convert it to List instead of IEnumerable and then pass to Observable Collection


List<string> sel =
    ( from i in MyObservable
      select
          i.Category
    ).Distinct();

ObservableCollection<string> categories = new ObservableCollection<string>(sel);
0
 

Author Comment

by:S7up1d
ID: 35021504
I am using .NET 4.0 CF for Windows Phone.  

While I can iterate through the list or the ienumerable and then copy into the ObservableCollection, I would rather not, I would imagine that there is a better way to do that than having two copies of the list in memory during the transfer process.

0
 
LVL 62

Expert Comment

by:Fernando Soto
ID: 35021617
@ kumar754;

Following your link shows the three constructors. Investigating a little bit more by clicking on "ObservableCollection<T> Class" just below the three constructors definition you will find the Change History as shown in the image below. So in version 3.5 just default constructor and in version 3.5 SP1 added new constructors.

Fernando Change History
0
 
LVL 12

Expert Comment

by:kumar754
ID: 35021885
@FernandoSoto

Thanks buddy, for the sharing this information. Yeah you are right, they added in 2008, good to know that I am using the same SP1 version.
0
 
LVL 62

Expert Comment

by:Fernando Soto
ID: 35022002
Hi S7up1d;

If you can upload the project and all its files I will attempt to see what is happening. If you can follow the instructions below.

To upload a file in zip format to the Experts Exchange Stuff web site at http://www.ee-stuff.com follow these steps:

1.  Zip the files or project to be uploaded
2.  The go to http://www.ee-stuff.com
3.  If you are prompted to log in use the same username and password you use on the main site here
4.  At the top of the page click on "Expert Area" tab
5.  Then click on "Upload a new file" link
6.  Follow the instructions on the page
7.  After a successful upload post the link of the file in the question.

Fernando
0
 

Author Comment

by:S7up1d
ID: 35047200
I am using .NET 4.0 For WINDOWS PHONE

not 3.5...

I will have to rewrite some of the code into an example I can post here.
0
 

Accepted Solution

by:
S7up1d earned 0 total points
ID: 35833628
I did not ever get an answer for this question that was even using the correct framework.
0
 
LVL 62

Expert Comment

by:Fernando Soto
ID: 35834270
You should of continued to work with us and follow through with your response from post 03/06/11 02:18 PM, ID: 35047200.
0
 

Author Closing Comment

by:S7up1d
ID: 35872711
Not on the correct framework at all, but I do want to give the points for the work done.

Thanks for your help!!!
0

Featured Post

Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article is for Object-Oriented Programming (OOP) beginners. An Interface contains declarations of events, indexers, methods and/or properties. Any class which implements the Interface should provide the concrete implementation for each Inter…
The article shows the basic steps of integrating an HTML theme template into an ASP.NET MVC project
This Micro Tutorial will give you a basic overview how to record your screen with Microsoft Expression Encoder. This program is still free and open for the public to download. This will be demonstrated using Microsoft Expression Encoder 4.
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

776 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question