Let’s say that you want to create your UI but in a dynamic way. Imagine a view which is based on a list of items you want to display. But this list can vary (depending on rights, or context). In this simple example, we want a label with a textbox, then a checkbox. We can do that with a TemplateSelector .
This is the final result; a simple list of settings with name and value.
First we need a model;
using Prism.Mvvm;
namespace DataTemplateSelectorDemo.Models
{
public enum MySettingType
{
Boolean,
String
}
public class MySetting : BindableBase
{
private string _name;
public string Name
{
get { return _name; }
set { SetProperty(ref _name, value); }
}
private string _stringValue;
public string StringValue
{
get { return _stringValue; }
set { SetProperty(ref _stringValue, value); }
}
private bool _boolValue;
public bool BoolValue
{
get { return _boolValue; }
set { SetProperty(ref _boolValue, value); }
}
private MySettingType _type;
public MySettingType Type
{
get { return _type; }
set { SetProperty(ref _type, value); }
}
public override string ToString()
{
return $"{Name} - {StringValue}";
}
}
}
Code language: C# (cs)
As you can see, there is a field named Type. This enum will determine which template we want to choose in the DataTemplateSelector
Now we can create the SettingTemplateSelector, a class inheriting from DataTemplateSelector. This class allows you to define two templates in your XAML StringTemplate (textbox) and BooleanTemplate (checkbox).
using DataTemplateSelectorDemo.Models;
using System.Windows;
using System.Windows.Controls;
namespace DataTemplateSelectorDemo.Helpers
{
public class SettingTemplateSelector : DataTemplateSelector
{
public DataTemplate StringTemplate { get; set; }
public DataTemplate BooleanTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var selectedTemplate = this.StringTemplate;
var setting = item as MySetting;
if (setting == null) return selectedTemplate;
switch (setting.Type)
{
case MySettingType.String:
selectedTemplate = this.StringTemplate;
break;
case MySettingType.Boolean:
selectedTemplate = this.BooleanTemplate;
break;
}
return selectedTemplate;
}
}
}
Code language: C# (cs)
You only need to declare in the ViewModel a list of settings and to initialize it.
using DataTemplateSelectorDemo.Models;
using Prism.Mvvm;
using System.Collections.Generic;
namespace DataTemplateSelectorDemo.ViewModels
{
public class MainWindowViewModel : BindableBase
{
#region Properties
private string _title = "DataTemplateSelector Demo";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
private List<MySetting> _settings;
public List<MySetting> Settings
{
get { return _settings; }
set { SetProperty(ref _settings, value); }
}
#endregion
public MainWindowViewModel()
{
this.LoadSettings();
}
private void LoadSettings()
{
this.Settings = new List<MySetting>
{
new MySetting
{
Name = "Setting1",
StringValue = "here is the string",
Type = MySettingType.String
},
new MySetting
{
Name = "Setting2",
BoolValue = true,
Type = MySettingType.Boolean
},
};
}
}
}
Code language: C# (cs)
Finally, we can use an ItemsControl binded to the list of settings to display. By setting the ItemTemplateSelector to our custom one, the correct template (BooleanTemplate or StringTemplate) will be selected automatically.
<Window x:Class="DataTemplateSelectorDemo.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
xmlns:helpers="clr-namespace:DataTemplateSelectorDemo.Helpers"
Title="{Binding Title}" Height="350" Width="525">
<Window.Resources>
<!--BOOL TEMPLATE-->
<DataTemplate x:Key="BooleanTemplate">
<StackPanel Orientation="Horizontal" Margin="10">
<TextBlock Text="{Binding Name}"></TextBlock>
<CheckBox IsChecked="{Binding BoolValue}" Margin="5, 0, 0, 0"/>
</StackPanel>
</DataTemplate>
<!--STRING TEMPLATE-->
<DataTemplate x:Key="StringTemplate">
<StackPanel Orientation="Horizontal" Margin="10">
<TextBlock Text="{Binding Name}"/>
<TextBox Width="100" Text="{Binding StringValue}" Margin="5, 0, 0, 0"/>
</StackPanel>
</DataTemplate>
<helpers:SettingTemplateSelector x:Key="SettingTemplateSelector"
BooleanTemplate="{StaticResource BooleanTemplate}"
StringTemplate="{StaticResource StringTemplate}"/>
</Window.Resources>
<Grid Margin="10">
<!--OUR LIST OF SETTINGS TO DISPLAY-->
<ItemsControl ItemsSource="{Binding Settings}"
ItemTemplateSelector="{StaticResource SettingTemplateSelector}">
</ItemsControl>
</Grid>
</Window>
Code language: HTML, XML (xml)
Happy coding! 🙂
[…] If you want more examples about TemplateSelector, have a look my other post about ItemsControl here. […]