Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF: switching UserControls depending on corresponding ViewModels (MVVM)

Tags:

I'll try to simplify the task I'm working on by imagining this example:

Let's suppose that we have the following hierarchy of model classes:

Animal
   Lion
   Snake
   Bird

...corresponding ViewModels:

AnimalCollectionViewModel
   AnimalViewModel
      LionViewModel
      SnakeViewModel
      BirdViewModel

... and corresponding views:

AnimalCollectionView
   LionView
   SnakeView
   BirdView

It's supposed that AnimalCollection contains a list filled with objects of different types of animals and below the list it has a property grid for setting the properties of a selected animal. Obviously the property grids will have different properties and should change when the type of a selected item changes.

The question is: How to implement switching of the property grids in WPF according to the MVVM pattern? Using what mechanism?

Currently I have an abstract enum property in the base ViewModel (AnimalViewModel.PropertyGridType = {Lion, Snake, Bird}) which the derived classes implement by returning corresponding values. And the AnimalCollectionView changes the property grid user controls depending on the value of this property. Something like this:

...

<UserControl.Resources>
    <Style x:Key="PropertyGridStyle" TargetType="ContentControl">
        <Style.Triggers>
            <DataTrigger Binding="{Binding PropertyGridType}" Value="Lion">
                <Setter Property="Content">
                    <Setter.Value>
                        <view:LionPropertyGridView />
                    </Setter.Value>
                </Setter>
            </DataTrigger>
            <DataTrigger Binding="{Binding PropertyGridType}" Value="Snake">
                <Setter Property="Content">
                    <Setter.Value>
                        <view:SnakePropertyGridView />
                    </Setter.Value>
                </Setter>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</UserControl.Resources>

<ContentControl Style="{StaticResource PropertyGridStyle}" />

...

But I'm not sure whether it is the right approach. (At least I don't like introducing the auxiliary enum property. Is it possible to deduce the necessary user control based on a ViewModel type?) Can anybody advise other options? Thanks in advance!

like image 722
Niccolo Avatar asked Feb 16 '11 15:02

Niccolo


2 Answers

Is it possible to deduce the necessary user control based on a ViewModel type?

You mean, like this?

<Window.Resources>
   <DataTemplate DataType="{x:Type vm:LionViewModel}">
      <v:LionView />
   </DataTemplate>
   <DataTemplate DataType="{x:Type vm:SnakeViewModel}">
      <v:SnakeView />
   </DataTemplate>
   <DataTemplate DataType="{x:Type vm:BirdViewModel}">
      <v:BirdView/>
   </DataTemplate>
</Window.Resources>

See "Applying a View to a View Model" in Josh Smith's article on MVVM.

Edit:

Here's a trivial example of type-based template selection that you can paste into Kaxaml to prove to yourself that it really works:

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:sys="clr-namespace:System;assembly=mscorlib">
  <Page.Resources>
    <sys:String x:Key="string">this is a string</sys:String>
    <sys:Int32 x:Key="int32">1234</sys:Int32>
    <DataTemplate DataType="{x:Type sys:String}">
      <TextBlock Foreground="Red" Text="{Binding}"/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type sys:Int32}">
      <TextBlock Foreground="Blue" Text="{Binding}"/>
    </DataTemplate>
  </Page.Resources>
  <StackPanel>  
    <ContentControl Content="{Binding Source={StaticResource string}}"/>
    <ContentControl Content="{Binding Source={StaticResource int32}}"/>
  </StackPanel>
</Page>
like image 75
Robert Rossney Avatar answered Oct 19 '22 08:10

Robert Rossney


You can use DataTemplateSelector for that. The method of choosing the right template is up to you. You can use enums or test for class type if you wish.

like image 35
Goran Avatar answered Oct 19 '22 09:10

Goran