Binding WPF control to multiple sources (not traditional multibinding) - wpf

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.

Related

Using Data sets in MVVM

What is the best practice to use data sets instead of an observable collection in MVVM to bind to grids. is it OK to have a property of type DataSet on the view model? How is the design time data set in this case?
One of the key concepts of the MVVM pattern is that the ViewModel is the "model of your view", it shapes your business model in such a way that it is easier to bind a UI (i.e. your View) to it.
You can certainly use a DataSet / DataTable to expose data from your ViewModel and bind it to your View. I don't see anything wrong with this approach. It is certainly valid MVVM!
Regarding design time data, it depends on how you are creating it. You cannot create a DataSet in XAML, so cannot use a XAML file within visual studio for your data. However, if you are programmatically creating design time data, i.e. within your ViewModel checking whether it is design-time, then creating data in your code, it will work just fine.

Large Model Collections in MVVM

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.

WPF CollectionViewSource in Custom Control misuse?

Should you use CollectionViewSource in the WPF Custom Control's code behind?
I'am asking because the CollectionViewSource.GetDefaultView(SOURCE) with .Filter set
changes the view so that all instances of the Control have the same view.
Doesn't it mean, that in the Custom Control's code behind, you should avoid use of CollectionViewSource ?
It depends on the desired behavior. E.g. if you had multiple lists of states on the screen and wanted to filter all of them by region at the same time, then this could be desired behavior. You can always force a different view source in cases where you do not want the items bound to the same filter criteria.
I think avoiding the use of CollectionViewSource until you understand the interactions of ItemsSource -> CollectionView -> Bound Item controls is probably a good idea, but I don't know that I would go so far as to say that you should avoid it in general.
I think it might be reasonable to say that if two lists on a form have different filtering/sorting requirements then they should be bound from different source properties (even if those properties are straight clones of a single underlying source). That way you can still apply filtering and storing at the CollectionViewSource level but without unintended consequences later on.

How can WPF Converters be used in an MVVM pattern?

Let's say I have a View that is bound to ViewModel A which has an observable collection Customers.
An advantage of this MVVM pattern is that I can also bind the View to ViewModel B which fills it with different data.
But what if in my View converter Converters to display my customers, e.g. I have a "ContractToCustomerConverter" that accepts a Contract and returns the appropriate Customer to be displayed.
The problem with this is that the converter exists outside the MVVM pattern and thus doesn't know that my ViewModel has another source for customers.
is there a way for the View to pass the ViewModel into the Converter so that it participates in the decoupling that the MVVM pattern provides?
is there a way for me to somehow include the Converter in my ViewModel so that the converter uses the current dependencies which ViewModel has available?
or are converters just glorified code-behind and thus not used in the MVVM pattern, so if you are using MVVM then you just create your own "converters" (methods on your ViewModel class) which return things like Image objects, Visibility objects, FlowDocuments, etc. to be used on the view, instead of using converters at all?
(I came upon these questions after seeing the use of Converters in the WPF demo application that comes with the MVVM Template Toolkit download, see the "Messenger Sample" after unpacking it.)
I usually don't use converters at all in MVVM, except for pure UI tasks (like BooleanToVisibilityConverter for instance). IMHO you should rather declare a Customer property of type CustomerViewModel in your ContractViewModel, rather than use a ContractToCustomerConverter
In this conversation there is a comment that agrees with Kent's position, not to use Converters at all, interesting:
A ViewModel is basically a value converter on steroids. It takes "raw" data
and converts it into something presentation-friendly, and vice-versa. If
you ever find yourself binding an element's property to a ViewModel's
property, and you're using a value converter, stop! Why not just create a
property on the ViewModel that exposes the "formatted" data, and then drop
the value converter altogether?
And in this conversation:
The only place I can see a use for
value converters in an MVVM
architecture is cross-element
bindings. If I'm binding the
Visibility of a panel to the IsChecked
of a CheckBox, then I will need to use
the BooleanToVisibilityConverter.
Converters should rarely be used with MVVM. In fact, I strive not to use them at all. The VM should be doing everything the view needs to get its job done. If the view needs a Customer based on a Contract, there should be a Customer property on the VM that is updated by VM logic whenever the Contract changes.
An advantage of this MVVM pattern is that I can also bind the View to ViewModel B which fills it with different data.
I dispute that claim. In my experience, views are not shared across different VM types, and nor is that a goal of MVVM.
For those effectively saying no "non-trivial converters" in the view, how do you handle the following?
Let's say that I have a Model of climate sensors that represents time series of readings from various instruments (barometer, hygrometer, thermometer, etc.) at a given location.
Let's say that my View Model exposes an observable collection of the sensors from my Model.
I have a View containing a WPF Toolkit DataGrid that binds to the View Model with the ItemsSource property set to observable collection of sensors. How do I represent the view of each instrument for a given sensor? By displaying a small graph (think Edward Tufte sparkline here) that is generated by converting the time series to an image source using a converter (TimeSeriesToSparklineConverter)
Here is how I think of MVVM: The Model exposes data to View Models. The View Model exposes behavior, Model data and state to View. Views do the job of representing Model data visually and providing an interface to behaviors consistent with the View Model state.
Thusly, I don't believe that the sparkline images go in the Model (the Model is data, not a particular visual representation of it). Nor do I believe that the sparkline images go in the View Model (what if my View wants to represent the data differently, say as a grid row just showing min, max, average, standard deviation etc. of the series?). Thus, it seems to me that the View should handle the job of transforming the data into the desired representation.
So if I want to expose the behaviors, Model data and given state for a certain View Model in a command-line interface instead of a WPF GUI, I don't want my Model nor my View Model containing images. Is this wrong? Are we to have a SensorCollectionGUIViewModel and a SensorCollectionCommandLineViewModel? That seems wrong to me: I think of the View Model as an abstract representation of the view, not concrete and tied to a particular technolgy as these names suggest they are.
That's where I am in my continually evolving understanding of MVVM. So for those saying not to use converters, what are you doing here?
I've been using Stackoverflow for years and this is accrual my first answer posted.
I think converters belongs to View in MVVM, consider the following situation:
App is developed by 3 teams, webapi team, webclient team and UI team. UI changed frequently so the webclient team (which receives data from webapi and put them into viewmodel) cannot always modify the viewmodel to satisfy UI needs. This becomes impossible when the UI team have different versions of design. So the UI team must have their own way to present the data and the solution is Converters.
Hope this helps someone.
I'll add my 2 cents to this discussion.
I do use converters, where it makes sense.
Explanation:
There are cases where you need to represent 1 value in Model in more ways in the UI. I expose this value through 1 type. The other is type is handled through converter. If you were to expose 1 value through 2 properties in VM, you would need to manually handle update notifications.
For example I have a model with 2 ints: TotalCount, DoneCount. Now I want both this values to be displayed in TextBlocks and additionally I want to display done percentage.
I solve this using DivisionConverter multi converter which takes 2 previously mentioned ints.
If I were to have special PercentDone in VM, I would need to update this property whenever DoneCount is updated.

How do you keep view logic out of the model and business logic out of the view-model in MVVM?

I can't quite figure out how to get the view model to be notified of changes in the model without adding a bunch of UI specific stuff like INotifyProperyChanged and INotifyCollectionChanged in my model or create tons of different events and do a bunch of things that feel like they're UI specific and should stay out of the model.
Otherwise I'd just have to duplicate all the business logic in the view-model to make sure everything is up to date, and then what's the point of having the model then?
One of the tricky ones that I have in my model is a property of a "Category" class. You can think of it as a tree structure and the property is all leaf-node descendants. Well in the model that property is generated on the fly recursively through all it's children, which is all fine and good. The view-model however needs to bind to that property and needs to know when it changes. Should I just change the model to accommodate the view-model? If I do then the view-model doesn't really do anything at this point, the model raises all the necessary notifications of changes and the view can just bind straight to the model. Also if the model was something I didn't have the source to, how would I get around this?
I disagree that INotifyPropertyChanged and INotifyCollectionChanged are UI-specific. They are in namespaces and assemblies that are not tied to any particular UI stack. For that reason, I typically put that kind of behavior as low in the system as I can (usually the data layer).
If there's some reason you don't want to put it at that level, that's fine. You can put it in at a higher level such as the service or UI layer. However, you need to make sure all changes to the data structures occur through that layer also.

Resources