I am binding to observable collections, but not sure how to filter and order them with linq. I need them to be observable, otherwise my bindings won't be notified of changes (right?). When you populate an observable collection, will it retain the order items were added to it?
I am not sure where to go from here.
For databinding, is there another type of collection that is observable, but that you can use linq on?
If you need to provide filtering and sorting on top of your list data, then you should probably use CollectionViewSource for binding rather than ObservableCollection. Geoff Hudik's post: WP7 In-App Searching, Filtering covers this.
ObservableCollection is the recommended collection to use when you know that the underlying data will change.
It will retain the order of items in which they were added
You can use other collections for databinding as well, Linq can be used on pretty much anything that implements IEnumerable.
Related
I have an interesting problem. I have an existing module that exposes and maintains an observable collection of entities. I want to have an observable collection or some implementation of INotifyCollectionChanged that keeps in step with the adds and removals of items from the other collection but contains wrapper classes (view models) rather than the entities themselves.
I understand shallowly how the CollectionChanged event works, but I want to either handle that completely which I'm not sure I know how to do, or otherwise use an existing pattern. Can anyone help me with this?
Continuous Linq is designed to do exactly that.
So I've got an object that has an observable collection. Most places I bind to this collection I only want the user to select a single item. But in one place I want the combobox to include an all items option.
Is the way to do this simply with xaml converter?
It seems like doing it in the view model would be a good idea, but it's really a lot dependency object goop to basically wire up an collection that is two objects deep for an on change event, where as the xaml converter just works.
But I always feel like xaml converters should be generic and reusable, where in this instance, the xaml converter would be more of a one off.
Of course the third option would be to create one off list for UI in the object that contains the standard observable collection. But this seems to be mixing the logic and presentation in a way that makes me uncomfortable.
Take a look at CompositeCollection. It lets you concatenate multiple collections into a single collection -- sort of the XAML equivalent of the LINQ Concat. It implements INotifyCollectionChanged, so it should be able to react to changes if some of its inner collections are ObservableCollections.
CompositeCollection also lets you add individual elements, so you wouldn't even need to wrap your "All Items" in a collection of its own. (Instead, you have to wrap collections in a CollectionContainer. See the examples on the CompositeCollection doc page.)
I had a similar need, and ended up using the solution discussed in this article: How To Select Null/None in a ComboBox/ListBox/ListView.
You can replace the "(None)" string on line 98 with "All" or something similar. Then just add logic in your ViewModel to treat a null value as "All" in whatever manner is appropriate. It's a little annoying to have an extra class lying around but it makes the code a lot cleaner if you do need this in several places.
Whilst implementing my first MVVM application in WPF, I've been wondering about the pros and cons of wrapping Model collections in related ViewModel collections to use in the View.
In our system we are likely to have several potentially large collections e.g. Order Lines in an Order, and Stock Items which could be selected for an Order Line. At present these are looked up from SQL in the Data Access layer, and then SqlDataReaders are looped around to create a collection of Model Objects.
To then loop around the collection of Model objects when creating a collection of ViewModel objects seems like an unnecessary overhead. When there are large collections of Model objects would it be better to expose these directly on the View?
Thanks in advance for your help, Mark
Edit
While reading up on this subject I found this MSDN article from July this year (reviewed by Josh Smith no less) which gives a pretty balanced view of MVVM, and in the 'Collections' section said this:
Another problem with collections is
determining when or if to wrap each
Model instance in the collection
within a ViewModel instance. For
smaller collections, the ViewModel may
expose a new observable collection and
copy everything in the underlying
Model collection into the ViewModel
observable collection, wrapping each
Model item in the collection in a
corresponding ViewModel instance as it
goes. The ViewModel might need to
listen for collection-changed events
to transmit user changes back to the
underlying Model.
However, for very large collections
that will be exposed in some form of
virtualizing panel, the easiest and
most pragmatic approach is just to
expose the Model objects directly.
Thanks very much for the comments so far, trying to limit the amount of data passed into the ViewModel, or using paginated or other suitable controls would reduce problems I'm sure, but I wonder if there would there still be situations where it would be better to simply bind to a collection of Model objects within the ViewModel?
I guess that it would really depend on how you want to go about displaying the data. Afterall the ViewModel is primarily there to handle the data that the View requires.
Assuming that your data layer provides you with just the data collections you could always restrict the creation of elements within the ViewModel depending on those that you actually want to see.
For example you may have a Datagrid to display Order Items for a given Order.
Thus you could have a ViewModel Property AllOrderItems bound to the datagrid and yet its getter is as follows:
public List<OrderItems> AllOrderItems
{
get{return this.DataAccessLayer.GetOrderItems().Where(x=>x.OrderNumber==this.OrderNumber).toList();
}
Here the DataAccessLayer is a class that holds cache database data and interfaces to the database. If kept as a singleton then data duplication within it will be reduced.
You can adapt your ViewModel to do as much or as little filtering of data from the DataAccessLayer as requried. The collections can be Observable if requried and the DataAccessLayer can generate events for VMs to react to for cases of new data being added, removed, saved to the database.
I am trying to do some databinding magic. I have a Shipments view that lists shipments, and provides filtering and ordering ability on the list. The filter string box, Delivery Status filters (checkboxes) and Ordering Radiobuttons are databound to properties in the ViewModel. I want to add the ability to save state and I have elected to do this by saving control states in an xml document. Previously I have done this before with little problem, using databinding to just read/write the values back and forth.
However, now I have a quandry. My filter controls are currently databound to items in the ViewModel. i can write code that changes their databinding from the xml to the ViewModel on load and vice versa, but that would be messy.
Is there a mechanism in place that I can use to achieve the ability to bind to two equal sources and have them updated at the same time?
This sounds like a concern for the view model.
Why not load the saved values into the view model, and have the view model decide what data to expose?
Then the view doesn't have to be concerned with managing data.
None that I'm aware of.
My opinion: I really wouldn't do this anyway - if your datacontext is the viewmodel, and the viewmodel has properties for the filter, you almost certainly should be persisting and retrieving the relevant viewmodel state to keep the state of the filters. Trying to save controlstate, then retrieve it, set it, and set the viewmodel based on the new controlstate sounds like a lot more work and much more prone to bugs.
I have several CollectionViewSource instances all used on the same ObservableCollection. I also have several controls that need to show filtered versions of the collection (hence the CollectionViewSources). The problem I'm having is that CollectionViewSource forces them to all have the same item selected. Is there some way to turn this off?
Thanks,
Jason Lewis
If you use the method (im not sure about this but CollectionViewSource in xaml probably does)
CollectionViewSource.GetDefaultView(this.ItemsSource);
multiple times it will only return the same ICollectionView (if we are talking about the same collection bound multiple times), this means if you apply a filter to one it apllies to all, also as the collection view tracks the current item the current item will be syncronised between the different views.
You can work around this by creating a CollectionView for each filter/selection you want to have by using
new CollectionView(this.ItemsSource as IList);
there are a few types that implement ICollectionView, CollectionView and ListCollectionView do. in the above code i did not get the default view i created a new one, so its filering/sorting is unique.
When you use items source wpf creates a collection view to wrap the collection, this collection view is the one that is returned in the GetDefaultView call, useful for every day situations but not the edge cases.
here is a blog post from bea that explains it a bit better