Using a ValueConverter as a DataTemplateSelector in Silverlight

This idea was proposed to me by a co-worker of mine by the name of Casey Gum.

A DataTemplateSelector allows you to select a DataTemplate dynamically into your view based on certain criteria in your code. Silverlight 3.0 doesn't have a DataTemplateSelector, however you can use a ValueConverter to do the same thing with just a little bit of additional code.
Let's say I have a few DataTemplates and I want to select one of them into my UserControl based on a criteria in my ViewModel. Here are my data templates in a file called ControlResourceDictionary.xaml:


<
ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
<DataTemplate x:Key="simpleTextBox">
<TextBox Style="{StaticResource MyStyle}"AcceptsReturn="True" VerticalScrollBarVisibility="Auto" Text="{Binding Value, Mode=TwoWay}" VerticalAlignment="Top" TextWrapping="Wrap" />
</DataTemplate>
<DataTemplate x:Key="simpleLabel">
<TextBlock Text="{Binding Name}" Style="{StaticResource MyLabelStyle}" />
</DataTemplate>
</
ResourceDictionary >

I could create a ValueConverter that selects one of them as follows:

public
class TypeToControlConverter : IValueConverter
{
private static readonly ResourceDictionary ControlResourceDictionary;
static TypeToControlConverter()
{
ControlResourceDictionary=
new ResourceDictionary
{
Source =
new Uri(
"/SandBox.MyControl.Experiment;component/Resources/
ControlResourceDictionary.xaml",
UriKind.RelativeOrAbsolute)
};
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
// Change up the binding so that you can use value to determine the data template that gets loaded.
var viewModel = value as MyViewModel;
DataTemplate dataTemplate = ControlResourceDictionary["simpleTextBox"] as DataTemplate;
if ((value as myViewModel).IsEditable == false)
dataTemplate = ControlResourceDictionary[
"simpleLabelDisplay"] as DataTemplate;
}
var loadedTemplate = dataTemplate == null ? null : dataTemplate.LoadContent();
return loadedTemplate;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}



The line in my view file to use the ValueConverter would look like the following:



<
UserControl.Resources>
<valueconverters:TypeToControlConverter x:Key="controlSelector" />
</UserControl.Resources>
<ContentControl Content="{Binding Converter={StaticResource controlSelector}}" />

Assuming I set up the Binding in the code behind to bind the DataContext of the View to the ViewModel, my ViewModel may look like the following:

public class MyViewModel :
INotifyPropertyChanged
{
public string Name {get; set;}
private string val = "";
public string Value
{
get {return val;}
set {value = val; RaisePropertyChanged("Value");
}
public bool IsEditable {get; set;}
}



This scenario in MVVM should get you around the problem of not having the DataTemplateSelector.