17

I have a method in a Silverlight app that currently returns an IList and I would like to find the cleanest way to turn this into an ObservableCollection so:

public IList<SomeType> GetIlist()
{
   //Process some stuff and return an IList<SomeType>;
}

public void ConsumeIlist()
{
   //SomeCollection is defined in the class as an ObservableCollection

   //Option 1
   //Doesn't work - SomeCollection is NULL 
   SomeCollection = GetIlist() as ObservableCollection

   //Option 2
   //Works, but feels less clean than a variation of the above
   IList<SomeType> myList = GetIlist
   foreach (SomeType currentItem in myList)
   {
      SomeCollection.Add(currentEntry);
   }
}

ObservableCollection doesn't have a constructor that will take an IList or IEnumerable as a parameter, so I can't simple new one up. Is there an alternative that looks more like option 1 that I'm missing, or am I just being too nit-picky here and option 2 really is a reasonable option.

Also, if option 2 is the only real option, is there a reason to use an IList over an IEnurerable if all I'm ever really going to do with it is iterate over the return value and add it to some other kind of collection?

Thanks in advance

Simon_Weaver
  • 140,023
  • 84
  • 646
  • 689
Steve Brouillard
  • 3,256
  • 5
  • 41
  • 60
  • 2
    update for silverlight 4: ObservableCollection DOES now have a constructor that will take an IList or IEnumerable as a parameter – Simon_Weaver Nov 01 '10 at 00:36

8 Answers8

32

You could write a quick and dirty extension method to make it easy

public static ObservableCollection<T> ToObservableCollection<T>(this IEnumerable<T> enumerable) {
  var col = new ObservableCollection<T>();
  foreach ( var cur in enumerable ) {
    col.Add(cur);
  }
  return col;
}

Now you can just write

return GetIlist().ToObservableCollection();
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • 2
    I had considered that, and probably should have said so. Mostly I want to be sure that there wasn't something buit-in that I was missing. – Steve Brouillard Apr 08 '09 at 20:19
  • 1
    @Steve unfortunately I dont' think you overlooked anything. – JaredPar Apr 08 '09 at 20:22
  • Wouldn't it give problems when you add a new item to the list. It will loose track of the item since you are created a new ObservableCollection. – azamsharp Jul 02 '09 at 20:18
  • @azamsharp: Indeed. 1) To* methods always make copies of their input 2) since the source doesn't provide INotifyCollectionChanged there ain't no way to detect changes to the original anyways. – David Schmitt Feb 18 '10 at 08:24
  • Silverlight 4 now has a constructor to 'new up' an ObservableCollection - so you can just do that instead of enumerating yourself. – Simon_Weaver Nov 01 '10 at 00:35
21

Er...

ObservableCollection does have a constructor that will take an IEnumerable<T>, and IList<T> derives from IEnumerable<T>.

So you can "just new one up"

Randolpho
  • 55,384
  • 17
  • 145
  • 179
  • The documentation appears to be incorrect. I've verified this with reflector.exe – JaredPar Apr 08 '09 at 20:21
  • Is that perhaps the WPF version of ObservableCollection? I'm working in Silverlight. Editing to include that in the TEXT and not just the tag. – Steve Brouillard Apr 08 '09 at 20:21
  • @JaredPar: Are you saying that you used reflector to verify that the Silverlight version has an IEnumerable constructor? – Randolpho Apr 08 '09 at 20:23
  • @Steve Brouillard: I totally missed the Silverlight tag. My bad. I went and found the documentation, which does not include the IEnumerable constructor. – Randolpho Apr 08 '09 at 20:24
  • Silverlight version of the documentation with only default constructor: http://msdn.microsoft.com/en-us/library/ms668604(VS.95).aspx – Beardo Apr 08 '09 at 20:25
  • @Randolpho I used reflector to verify WPF version does not have that constructor. Almost 100% silverlight does not either – JaredPar Apr 08 '09 at 20:31
  • I does have a List constructor, whihc he could have confused. But ultimately not relevant here. – Steve Brouillard Apr 08 '09 at 20:34
  • I'm soooo slow, I missed that completely. Not to mention I misread the post in the first place...ugghhh. – Steve Brouillard Apr 08 '09 at 20:48
  • @JaredPar: I'd verify either the .dll you're using or the version of it; I'm using WindowsBase.dll v3.0.0 (WPF version) and it certainly has the constructor in question; it not only compiles, but executes properly. I'm going to go test Silverlight now. – Randolpho Apr 08 '09 at 21:08
  • Ooh... just noticed something in the docs... the constructor was apparently added in .NET 3.0 SP2 / .NET 3.5 SP1. If you are using pre- service packs, that might be why you can't reflect on it. – Randolpho Apr 08 '09 at 21:11
  • but using the constructor for updating the observablecollection is not really useful if the observablecollection is used as binding in a View (which typically it is probably). Because then the view is not notified that it is in fact a complete new observablecollection – Erik Sep 11 '20 at 09:45
2

Not to reopen the thread but a constructor for ObservableCollection that takes IEnumerable has been added to silverlight 4

bcleary
  • 1,268
  • 10
  • 17
2

Silverlight 4 DOES have the ability to just 'new up' an ObservableCollection

Here's the shortened extension method possible in Silverlight 4.

public static class CollectionUtils
{
    public static ObservableCollection<T> ToObservableCollection<T>(this IEnumerable<T> items)
    {
        return new ObservableCollection<T>(items);
    }
}
Simon_Weaver
  • 140,023
  • 84
  • 646
  • 689
2

The extension method that JaredPar has given you is your best option in Silverlight. It gives you the ability to turn any IEnumerable into observable collection automatically simply by refering to the namespace, and reduces code duplication. There is nothing built in, unlike WPF, which offers the constructor option.

ib.

1
Dim taskList As ObservableCollection(Of v2_Customer) = New ObservableCollection(Of v2_Customer)
' Dim custID As Guid = (CType(V2_CustomerDataGrid.SelectedItem,  _
'         v2_Customer)).Cust_UUID
' Generate some task data and add it to the task list.
For index = 1 To 14
    taskList.Add(New v2_Customer() With _
                 {.Cust_UUID = custID, .Company_UUID, .City
                 })
Next

Dim taskListView As New PagedCollectionView(taskList)
Me.CustomerDataForm1.ItemsSource = taskListView
Stephan
  • 41,764
  • 65
  • 238
  • 329
1
        IList<string> list = new List<string>();

        ObservableCollection<string> observable = 
            new ObservableCollection<string>(list.AsEnumerable<string>());
Ragoczy
  • 2,907
  • 1
  • 19
  • 17
  • The Silverlight version of ObservableCollection only has the default constructor. Can't new one up and pass it anything to initialize it. – Steve Brouillard Apr 08 '09 at 20:32
0

You can do this:

public class SomeTypeCollection: ObservableCollection<SomeType>
{
    public SomeTypeCollection() : base() { }
    public SomeTypeCollection(IEnumerable<SomeType> IEObj) : base(IEObj) { 
 }
}

public ConsumeIlist
{
    public SomeTypeCollection OSomeTypeCllt { get; set; }
    MyDbContext _dbCntx = new MyDbContext();
     public ConsumeIlist(){
          OSomeTypeCllt = new 
   SomeTypeCollection(_dbCntx.ComeTypeSQLTable);
     }
}
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Hunab Ku
  • 31
  • 2