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!
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>
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With