13

In my WPF application I'd like to use LINQ as much as possible (especially to avoid foreach). But WPF works a lot with the ObservableCollection, and I can't use LINQ with these kind of collection. What can I do?

yoozer8
  • 7,361
  • 7
  • 58
  • 93
lamarmora
  • 1,116
  • 4
  • 16
  • 32

4 Answers4

18

Just for anybody else who may come across this issue with trying to filter an ObservableCollection but find that they can't.

Jon is absolutely correct in that there is no reason why you can't do this but the key thing for a newbie or for someone who has been developing with WPF for a while, is that you need to include the "using System.Linq;" namespace. As you soon as you do this, you can do a ".where" query on your object.

Mark P
  • 191
  • 1
  • 2
14

What makes you think you can't use LINQ with ObservableCollection<T>? It implements Collection<T> so it should be fine.

For example:

using System;
using System.Collections.ObjectModel;
using System.Linq;

class Test
{
    static void Main()
    {
        var collection = new ObservableCollection<int>()
        {
            1, 2, 3, 6, 8, 2, 4, 5, 3
        };

        var query = collection.Where(x => x % 2 == 0);
        foreach (int x in query)
        {
            Console.WriteLine(x);
        }
    }
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thank you. Sorry. I remember there were problems with some queries, but now I have tried and everything works. – lamarmora Jul 15 '10 at 16:21
  • 1
    The resulting query is an IEnumerable. Is there a clean way of going back into an ObservableCollection ? – tofutim Jan 03 '14 at 22:03
  • @tofutim: No, not as far as I'm aware I'm afraid. – Jon Skeet Jan 03 '14 at 22:42
  • Clean way back? What about `new ObservableCollection(collection)`. Almost all (if not all) collection types have constructors accepting an IEnumerable as argument. – EluciusFTW Jan 14 '14 at 16:42
  • 2
    @ToaoG: That takes a copy of the data - it won't change when the original observable collection changes, which is what I'd expected tofutim to require. I could have misunderstood though. – Jon Skeet Jan 14 '14 at 16:44
  • Maybe this is not the right place for my method, but I do that all the time, e.g., in a method with signature `public ObservableCollection DoSomething(ObservableCollection _input)` where in the method I use Linq, e.g., `var subset = _input.where(n = > n.condition)` and then `return new ObservableCollection(subset)` – EluciusFTW Jan 14 '14 at 16:49
  • @ToaoG: It depends on what you're trying to observe. Normally I'd expect an observable collection to want to be fairly closely linked to the original source collection. But YMMV. – Jon Skeet Jan 14 '14 at 16:50
  • Yeah I typed my answer a bit hastily, the proper signature should be `public ObservableCollection DoSomething(IEnumerable _input)`. But what I said happens very naturally if your view displays an ObservableCollection which should be filtered according to some user input - then I use above code in the getter of the bound ObservableCollection. Is there a better way? – EluciusFTW Jan 14 '14 at 16:57
  • 1
    @ToaoG: If you're going to filter it so that you don't *actually* observe any changes in the original data, what good is it doing you to use ObservableCollection at all? What changes will you observe? – Jon Skeet Jan 14 '14 at 16:58
  • Say you have a property called data of type `List` with all the data, and bind a property of type `ObservableCollection` to your view. As getter `get { return new ObservableCollection(data.Where(n => n.name == 'What User entered in a textbox')); }`. Then the view will only see the part of the data that the user requests. – EluciusFTW Jan 14 '14 at 17:05
  • 1
    @ToaoG: You didn't answer my question: why bother using an ObservableCollection at all, if you're not going to be able to observe any changes? (Because it's a copy of the data.) – Jon Skeet Jan 14 '14 at 17:07
  • @JonSkeet Is a possible solution to wrap every LINQ operator that describes ObservableCollection instead of IEnumerable and forwards a event notification on CollectionChanged. It will trigger everytime the underlying collection changes as opposed to when the query result changes, but that's not unheard of. Are ObservableCollection objects expensive? It's a bit weird that there is no IObservableCollection interface. – Tormod Apr 23 '17 at 07:20
  • @Tormod: It sounds like you should possibly look at Reactive Extensions, which is more designed around the idea of reacting to changes as a fundamental operation. – Jon Skeet Apr 23 '17 at 07:22
1

The OP asked especially for the LINQ ".ForEach()" Method, which cannot be used on ObservableCollection< T >, since it's implemented for List< T > only.

There is another SO-Topic, where I found my solution: https://stackoverflow.com/a/200584/2408978

dba
  • 1,159
  • 1
  • 14
  • 22
0

You need my ObservableComputations library maybe. That is .NET API designed especially to work with LINQ like queries to ObservableCollection in WPF and other .NET UI frameworks that support binding to INotifyCollectionChanged and INotifyPropertyChanged objects (Xamarin, Blazor).

Igor Buchelnikov
  • 505
  • 4
  • 14