Dynamic column generation in WPF DataGrid - wpf

I have an object which has some 30 properties, depending on who is viewing the data, I need to present just 10-12 properties to him.
These properties will form the columns of the WPF datagrid. I am using .Net 4.0
However, all this will happen at run time. I need to do this is the MVVM way.
Any direction as to how to achieve this will be appreciated.
regards,

You have two options as far as I can see.
1) Expose a ViewableDetailsType enum property from your ViewModel that tell you what kind of view of the data you should show. In the view you can then create triggers in your DataGrid to set the Columns property of the grid to manually show the appropriate columns.
2) A better way would be to create wrapper, DTO type ViewModel objects for your underlying model object. One for each view of the object you want to expose. You then expose a collection of the appropriate wrapper objects to the view, and the DataGrid can use auto columns.
This is slightly more work, but it is truer to MVVM since the data hiding is taking place in the ViewModel, and can thus be tested.

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.

WPF listview, Load, Save & Add

I have a columned listview who's items I would like to store in an XML file.
What's the best way to go about loading, saving and adding items?
best way is to use MVVM :), that way your View simply represents the data in the UI. Actual DomainModel/BusinessObject resides outside your View.
And then you can use number of persistance methods:
XML Serialization
ORM (Object Relation Mapping), which will persist/save the BusinessObject into Database and back
Step by step way:
Create/Define your BusinessObject(DomainModel, i.e. Person class)
Use DataTemplate to Bind to Collection from your ListView
In your ViewModel, you can than say PersonCollection.Save/Load etc

Binding WPF control to multiple sources (not traditional multibinding)

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.

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 to display in each ListBoxItem textblocks with binding to a filelds of a different tables

Greetings to all and sorry for my English!
I have a ListBox, it's ItemsSource = myClientsList.DefaultView. The Items of ListBox have a template (ControlTemplate), that is defined in a in a separate resource file.
Every Item contains a little TextBlock's, Text -property of each have a binding to fields of my Object myClientsList.
I need to add in a this item template more TexBlock's and each of them must have binding to fields of another my class myOrdersList. - (So I wish to view on each line of ListBox information from different tables of my database - this is a question).
Problem in that that ListBox's ItemsSource have a link to object myClientsList and I cann't set myOrderList to ItemSource of same ListBox. So i must find a way to specify TextBlock.DataContext wich inside ControlTemplate or how it's possible to solve this problem in another way?
p.s. I'm a new in .Net and WPF and probably have a mistakes in my explanation - sorry for it.
It sounds like you have a DataGrid type of display and want to add more columns in order to display the order information for a given client. If this is the case, you are going to have to do a couple of things. First, you will need to create a composite object that stores information for both entities into a single object (so each row of your control has all the data it needs to display). Secondly, I would recommend using an actual DataGrid control to display rows instead of templating a ListBoxItem. The ListView with a GridView built into the framework isn't great, so I would recommend the WPFToolkit's DataGrid for a free option.
There are two issues here, if I've understood the question: how do you create a single collection containing both Clients and Orders, and how do you display Clients and Orders in different ways within the same ListBox?
Regarding the first, you can do this using a CompositeCollection.
Regarding the second, define two DataTemplates instead of a ControlTemplate. As the key of each DataTemplate, use the type of the object it is going to present e.g.
<DataTemplate x:Key="{x:Type local:Client}">
Alternatively, use ItemsControl.ItemTemplateSelector to explicitly point at different DataTemplates depending on the type of item. Ot if you really have to use ControlTemplates, check out ItemsControl.ItemContainerStyleSelector.

Resources