how to create a 'live' collection that's the concat/union/whatever of 2 (or more) other collections?
NOTE: I can certainly brute-force this myself by making a class that implements INotifyCollectionChanged, but it feels like something that's already been solved, and I just haven't looked in the right place(s) yet.
In a few places in my viewmodel, I have collections that are effectively some particular entity set off of my domain context (we'll call it SomeEntitySet) with some small handful of 'special' instances added to it (at the front, at t开发者_JAVA百科he end, sometimes both). Currently I implement this as a simple ObservableCollection (we'll call it SupplementedEntitySet) and whenever I update the particular entity set, I have the callback also re-populate this SupplementedEntitySet. The entity set off of the domain context is readonly, so I can't add the 'special' instances there (and I really wouldn't want to anyway, as I don't want them written back to the database).
For this scenario, let's assume 1) I don't want to modify the RIA query to include these 'special' entities 2) I don't want to include binding converters at use sites to add them, etc.
While you likely wouldn't use this particular mechanism to do so, as an example scenario, let's say you have a list of categories coming back from the RIA call, but you want the collection to which you bind your combobox to have a special 'All items' category as well (and again, don't want to add it via converter or the like).
At a conceptual level, I'd normally look at something like Rx, but at least at the moment, I don't see how I would use that such that I'd still have a 'pull' collection useful for binding as the ItemsSource to some ItemsControl (grid, combobox, listbox, whatever)
Certainly this is a specific case of a more generic problem - how to have 'live' linq query outputs - you might want 'live' collections that are subsets of the source, or a projection, or some combination, or whatever. Much like we have LINQ providers for IEnumerable, IQueryable, and IObservable, it feels like we could/should have a provider for something like IObservableCollection (where IObservableCollection : ICollection, INotifyCollectionChanged or something similar)
That more generic framework/provider/whatever seems pretty complicated (especially implementing it in a performant way), so at least at the moment, I'm just looking for the particular scenario of a source collection (in this case, a ObservableCollection, even though the DomainContext only exposes them as IEnumerable)
Am I thinking about this wrong?
You mentioned Rx in your question, but you weren't sure how to end up with a "pull" collection for binding. It's easy. You just need to "push" your "pull" collections.
Start with a subject like this:
var updatedItems = new Subject<IEnumerable<string>>();
Subjects are IObservable
& IObserver
at the same time. So each time you fetch the items from RIA services you just call OnNext
on the subject.
// first result from RIA service call
updatedItems.OnNext(new [] { "A", "B", });
// sometime later another result
updatedItems.OnNext(new [] { "X", "Y", });
Now you can update your ObservableCollection
like this:
var itemsObservableList = new ObservableCollection<string>();
var extras = new [] { "<all items>" };
var supplementedItems =
from items in updatedItems
select extras.Concat(items);
supplementedItems.Subscribe(items =>
{
itemsObservableList.Clear();
items.Run(itemsObservableList.Add);
});
This way you just need to update the subject once and all of your associated view models get updated automagically. :-)
精彩评论