What is the best way to change viewmodel type in contentcontrol

Topics: Questions
Dec 20, 2012 at 6:49 AM
Edited Dec 20, 2012 at 6:52 AM

The problem is: we have 2 subtypes of models. They all derived from base class Purchase and stored in one BindingList<Purchase>.

Our target - basket window in Master-Details style. User can see purchases in ListBox with different ItemTemplates for each subtype of Purchase (I.e. for goods - small control with quantity and name, for fuel - small control pump number, nozzle, fuel type, volume etc). When user click on purchase at the right side we must show details about purchase. For goods - big control with quantity and name, for fuel - big complex control with pumps sheme and other data.

Solution from my view (biggest problem - i'm a C++ programmer and using C# and WPF for 4 months and i have a little knowledge how to use C# and WPF at its best):
1) StyleTrigger or DataTrigger or just a DataTemplate to select correct UserControl for ListBox.
2) To show correct Details i planned to use ContentControl, but in my test project i have problem with it.

<ContentControl Grid.Column="1" Grid.Row="0" Content="{Binding ActiveViewModel}"/>
...
//Somwhere inside OnCcommand handler
ActiveViewModel = m_ViewModelsFactory.CreateSalesViewModel(Sales);
//In another OnCcommand handler
ActiveViewModel = m_ViewModelsFactory.CreateHelpViewModel(Help);

 This code used in main window to show screens (sales, help,statistic). The problem is when i set ActiveViewModel first time everything works fine and . But when i try to change ActiveViewModel i get exception "No parameterless constructor defined for this object". Looks like i'll get same problem when will try to implement Master-Details part.

Any suggestions how to do it in best way? We already thinking about StackPanel with two Views for goods and fuel purchase, hiding each other on item select. Is it ok?

Developer
Dec 26, 2012 at 7:33 PM
Edited Dec 26, 2012 at 7:38 PM

Hi, a good starting point is taking a look into the Catel approach to build master/detail view, but probably to solve your issue (with a clever solution) you need inject views with Prism following the master/detail approach described on Prism Training Kit (UIComposition Lab).

The bad news is the approach described on Prism Training Kit is bit complex (MVP pattern and the use of controllers).

The good news is that Catel also comes with an extension for Prism and you can inject a view from it's view model reference (just with MVVM pattern and with a View-Model first approach).

See also:

http://likewastoldtome.blogspot.com/2012/05/catel-creates-perfect-combination-with.html

http://likewastoldtome.blogspot.com/2012/11/more-about-catel-and-prism-in.html

http://catel.catenalogic.com/?catel_extensions_prism.htm

Dec 28, 2012 at 5:53 AM

Hi, thanx for the answer!
Looks like there is no simple way. It's time to learn another new library. Thanks for your articles. With extension using Prism looks not as hard as i thought.

Coordinator
Dec 30, 2012 at 1:00 PM

There is no need for Prism here. Although prism is very nice if you want modular information in your application, Catel can perfectly handle the situation you describe above.

1) Make sure you have an DataTemplateSelector which knows what view to use for which view model in the list box or items control.

2) The listbox will load the right view based on the datatemplateselector, and then Catel does all the magic for you. It will automatically try to inject the datacontext (item of the data template) into the view model.

If the view model has an empty constructor, it will always create the view model. However, it is best to use the right injection here. Make sure that the view model that is used for the views inside the items control.

For performance reasons, it might be wise to turn off some validation controls if you don't need them, especially if you have lots of catel controls in a single list. Take a look at the performance considerations for more details.

Jan 2, 2013 at 3:32 AM
Edited Jan 2, 2013 at 3:34 AM

Hi again and happy new year!

Ok, first problem can be solved without prism, but how can i solve my second and biggest problem without prism? Why i get exception when trying to change type in contentcontrol and not get new View generated for new value? Or i'm just doing it wrong and everything should work fine?

Coordinator
Jan 2, 2013 at 2:48 PM

What is the exception? And what is the inner exception? Did you try to turn on Catel logging to find out why the issue is occuring? You can enable Catel logging using this in your app startup:

LogManager.RegisterDebugListener();

Then you will get a LOT of logging, but in most cases it will show you what's going wrong.

Jan 2, 2013 at 4:12 PM

The problem is when i set ActiveViewModel first time everything works fine and . But when i try to change ActiveViewModel i get exception "No parameterless constructor defined for this object".

Log already enabled. As i remembmer before exception was thrown i'v seen view discovery or something similar in log. Will post more details after 8 january.