WPF LINQ and the ObservableCollection
Solution 1
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);
}
}
}
Solution 2
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.
Solution 3
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
lamarmora
Updated on July 05, 2022Comments
-
lamarmora almost 2 years
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? -
lamarmora almost 14 yearsThank you. Sorry. I remember there were problems with some queries, but now I have tried and everything works.
-
tofutim over 10 yearsThe resulting query is an IEnumerable. Is there a clean way of going back into an ObservableCollection<int> ?
-
Jon Skeet over 10 years@tofutim: No, not as far as I'm aware I'm afraid.
-
EluciusFTW over 10 yearsClean way back? What about
new ObservableCollection<int>(collection)
. Almost all (if not all) collection types have constructors accepting an IEnumerable<T> as argument. -
Jon Skeet over 10 years@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.
-
EluciusFTW over 10 yearsMaybe 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<T> DoSomething(ObservableCollection<T> _input)
where in the method I use Linq, e.g.,var subset = _input.where(n = > n.condition)
and thenreturn new ObservableCollection<int>(subset)
-
Jon Skeet over 10 years@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.
-
EluciusFTW over 10 yearsYeah I typed my answer a bit hastily, the proper signature should be
public ObservableCollection<T> DoSomething(IEnumerable<T> _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? -
Jon Skeet over 10 years@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?
-
EluciusFTW over 10 yearsSay you have a property called data of type
List<T>
with all the data, and bind a property of typeObservableCollection<T>
to your view. As getterget { return new ObservableCollection<T>(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. -
Jon Skeet over 10 years@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.)
-
derekantrican over 7 yearsThanks for the additional answer! That was my issue :)
-
Tormod about 7 yearsThe resulting ObservableCollection will not update if the query result update as a consequence of the underlying source being updated.
-
Tormod about 7 years@JonSkeet Is a possible solution to wrap every LINQ operator that describes ObservableCollection<T> instead of IEnumerable<T> 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<T> interface.
-
Jon Skeet about 7 years@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.