Switchable content

Code Behind

Extend the ContentControl class to add a template selector to it

public class ContentControlEx : ContentControl
{
	public DataTemplateSelector TemplateSelector
	{
		get { return (DataTemplateSelector)GetValue(TemplateSelectorProperty); }
		set { SetValue(TemplateSelectorProperty, value); }
	}

	public static readonly DependencyProperty TemplateSelectorProperty =
		DependencyProperty.Register("TemplateSelector", typeof(DataTemplateSelector), typeof(ContentControlEx), new PropertyMetadata(null));

	protected override void OnContentChanged(object oldContent, object newContent)
	{
		base.OnContentChanged(oldContent, newContent);
		if (this.TemplateSelector != null)
		{
			this.ContentTemplate = this.TemplateSelector.SelectTemplate(newContent, this);
		}
	}
}

Main.xaml

-Resource imports the templates/styles file (see below).
-In this example content in column 1 is switchable via ContentControlEx (see above) based on what item is selected in xyz (in column 0, which is a listbox/treeview etc)

<ResourceDictionary.MergedDictionaries>
	<ResourceDictionary Source="DetailsTemplates.xaml"/>
</ResourceDictionary.MergedDictionaries>

<ListBox x:Name="xyz" Grid.Column="0" Padding="5" BorderThickness="0"
	SelectionMode="Single"
	ItemTemplate="{StaticResource EmployeeTemplate}"
	ItemsSource="{Binding Employees}"
	/>

<local:ContentControlEx Grid.Column="1"
	TemplateSelector="{StaticResource DetailsTemplateSelector}"
	DataContext="{Binding Path=SelectedItem, ElementName=xyz}" Content="{Binding}" />

As you can see, content is bound to {Binding}, this is because column 0 and 1 both use the same data (an Employee) so we can simply bind to the SelectedItem in the listbox or w/e you are using. Column 0 only shows his/her name and on selection, column 1 will show a whole lot more.

DetailsTemplates.xaml

-Provides the DetailsTemplateSelector used by ContentControlEx above
-Holds styles and DataTemplates we want to use

<local:MasterDetailTemplateSelector x:Key="DetailsTemplateSelector"
	EmployeeTemplate="{StaticResource EmployeeDetailsTemplate}"
	OfficeTemplate="{StaticResource OfficeDetailsTemplate}"/>

<Style TargetType="TextBlock" x:Key="myKey">
....
</Style>
<DataTemplate x:Key="EmployeeTemplate">
	<StackPanel Orientation="Horizontal">
		<TextBlock Text="{Binding FirstName}" Margin="5,0" />
		<TextBlock Text="{Binding LastName}" />
	</StackPanel>
</DataTemplate>
			
<DataTemplate x:Key="EmployeeDetailsTemplate">
	<Grid>
		<local:UCDataTempl />
	</Grid>
</DataTemplate>
<DataTemplate x:Key="OfficeDetailsTemplate">
	....
</DataTemplate>

-So in here we got our styles (cut out), the DataTemplate for column 0 (the employee selector) and then the DateTemplate for column 1 (the detailed view for selected employee.)

-More templates can be put in here, like an OfficeDetailsTemplate in case you’d want to use a treeview where employees are child nodes of offices. The template selector will select the appropriate template based on the SelectedItem’s type.

-I set the details template to a user control so I can graphically design it. Within this control I can still access Employee data by simply using “{Binding Name}” etc. without additional configuration.

Code Behind (Seperate file called MasterDetailTemplateSelector.cs)

-Switch to the appropriate data template based on what was selected
-This is automatically called by ContentControlEx when it’s content changes (so when the selected item in “xyz” changes because that’s what it’s bound to.)

public class MasterDetailTemplateSelector : DataTemplateSelector
{
	public DataTemplate OfficeTemplate { get; set; }
	public DataTemplate EmployeeTemplate { get; set; }

	public override DataTemplate SelectTemplate(object item, DependencyObject container)
	{
		Office company = item as Office;
		if (company != null)
		{
			return this.OfficeTemplate;
		}

		Employee employee = item as Employee;
		if (employee != null)
		{
			return this.EmployeeTemplate;
		}

		return base.SelectTemplate(item, container);
	}
}

Leave a Reply

Your email address will not be published. Required fields are marked *