Solved

Get uniqe property list from ObservableCollection using Linq

Posted on 2011-02-26
25
2,664 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
 

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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
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

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Welcome my friends to the second instalment and follow-up to our Minify and Concatenate Your Scripts and Stylesheets (http://www.experts-exchange.com/Programming/Languages/.NET/ASP.NET/A_4334-Minify-and-Concatenate-Your-Scripts-and-Stylesheets.html)…
A long time ago (May 2011), I have written an article showing you how to create a DLL using Visual Studio 2005 to be hosted in SQL Server 2005. That was valid at that time and it is still valid if you are still using these versions. You can still re…
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

744 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

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now