Search code examples
wpfdatatemplatecontentcontrol

difference when setting ContentTemplate via name than via type inference


I have recently start to learn WPF + MVVM. It is possible I have the wrong end of the stick or the wrong stick completely with the way things should be done.

I am trying to create a simple order app, it has order items, each order has lineitems. There are two sections on the main page, (to start with they were both usercontrols).

The top is bound to the list of orders. The bottom is bound to the currently selected order, (the idea being it will display the detail of that order).

The details view needs to be able to view / edit and add new items. To this end I thought I should have two views / templates, the edit order view and the new order view / template. During my reading I came across datatemplates and thought this would be a good way to achieve this.

In my mainwindow.xaml I have the list of orders view bound as follows:

<ContentControl Content="{Binding Path=OrdersViewModel}"

The view is hooked up in the resources file with:

<DataTemplate DataType="{x:Type vm:AllOrdersViewModel}">
    <vw:AllOrdersView />
</DataTemplate>

This works great, when the app starts up they orders are displayed. I did the same with the order detail to start with (i.e. it only had the datatype set rather than any key defined. This worked well, if no order was selected then the view would not display, when an order was selected it would show up.

I am currently trying to change this to a template so that I can dynamically switch the template / view so that when they user clicked NEW order (the viewmodel has an Enum that states the current state of an order, so I would check against the enum value), the view should change.

If I try the following it will blow up. The app starts, the list of orders is displayed (at this point no orders are selected), and the details view is displayed, then one of the converters will blow up due to dependencyproperty.unsetvalue, (side note, should I always check for that?). Ideally I do not want the view to be shown until an order is selected:

<ContentControl Content="{Binding Path=OrderViewModel}" ContentTemplate="{StaticResource ordertemplate}" />

   <DataTemplate x:Key="ordertemplate">
       <TextBlock Text="hello" />
    </DataTemplate>

I have two questions mainly:

1) how would I stop the template from being displayed until it has data to display?

2) how could I switch the views / templates dynamically based on an enum?


Solution

  • The most straightforward mechanism to use for this situation would be a DataTemplateSelector, which contains code that you write that can examine the bound object, in this case your ViewModel, and choose the appropriate template to use, including handling the case of no detail selection.

    <ContentControl Content="{Binding Path=OrderViewModel}" 
                    ContentTemplateSelector="{StaticResource MyCustomSelector}" />