Reputation: 47
I have 3 DataTemplate in my Window.Resources, strongly typed to three different classes:
<DataTemplate x:Key="myTemplateA" DataType="{x:Type local:SampleClassA}">
<Grid>
<TextBlock Text="{Binding Path=SampleProperty1}"></TextBlock>
<TextBlock Text="{Binding Path=SampleProperty2}"></TextBlock>
<TextBlock Text="{Binding Path=SamplePropertyA}"></TextBlock>
</Grid>
</DataTemplate>
<DataTemplate x:Key="myTemplateB" DataType="{x:Type local:SampleClassB}">
<Grid>
<TextBlock Text="{Binding Path=SampleProperty1}"></TextBlock>
<TextBlock Text="{Binding Path=SampleProperty2}"></TextBlock>
<TextBlock Text="{Binding Path=SamplePropertyB}"></TextBlock>
</Grid>
</DataTemplate>
<DataTemplate x:Key="myTemplateBase" DataType="{x:Type local:SampleClass}">
<Grid>
<TextBlock Text="{Binding Path=SampleProperty1}"></TextBlock>
<TextBlock Text="{Binding Path=SampleProperty2}"></TextBlock>
</Grid>
</DataTemplate>
And a little DataTemplateSelector:
<local:SampleDataTemplateSelector x:Key="myBindPropertyTemplateSelector"
TemplateA="{StaticResource myTemplateA}"
TemplateB="{StaticResource myTemplateB}"
SampleClassBaseTemplate="{StaticResource myTemplateBase}" />
Obviously there is the class for DataTemplateSelector, called SampleDataTemplateSelector
Public Class SampleDataTemplateSelector
Inherits DataTemplateSelector
Public Property TemplateA As DataTemplate
Public Property TemplateB As DataTemplate
Public Property SampleClassBaseTemplate As DataTemplate
Public Overrides Function SelectTemplate(item As Object, container As DependencyObject) As DataTemplate
If item Is Nothing Then Return SampleClassBaseTemplate
If item.GetType.Equals(GetType(SampleClassA)) Then
Return TemplateA
End If
If item.GetType.Equals(GetType(SampleClassB)) Then
Return TemplateB
End If
Return SampleClassBaseTemplate
End Function
End Class
DataTemplateSelector must discriminate 3 simply classes: SampleClass and 2 derived classes SampleClassA, SampleClassB.
Public Class SampleClass
Public Property SampleProperty1 As String = "Class SampleClass Property1"
Public Property SampleProperty2 As String = "Class SampleClass Property2"
End Class
Public Class SampleClassA
Inherits SampleClass
Public Property SamplePropertyA As String = "Class SampleClassA"
End Class
Public Class SampleClassB
Inherits SampleClass
Public Property SamplePropertyB As String = "Class SampleClassB"
End Class
In my window xaml the ContentControl is set like follow:
<ContentControl Content="{Binding BindProperty}" ContentTemplateSelector="{StaticResource myBindPropertyTemplateSelector}" />
Where BindProperty is a property defined on window code behind:
Dim myBindProperty As SampleClass
Public ReadOnly Property BindProperty As SampleClass
Get
Return myBindProperty
End Get
End Property
After all, in my window Load event there is the BindProperty initialization
Private Sub Window_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
myBindProperty = New SampleClassA()
End Sub
There's no compile errors. In execution, the item argument on SampleDataTemplateSelector's SelectTemplate routine is ever Nothing, so it can't choose the right template... and shows nothing. What I am doing wrong?
Upvotes: 1
Views: 4067
Reputation: 4322
I recreated your project and it does work if you add DataContext = Me to Window_Loaded. I changed your templates to use a StackPanel instead of a Grid (so the text blocks didn't overlap each other). Here is a complete, working version:
MainWindow.xaml
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication20"
Loaded="Window_Loaded"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate x:Key="myTemplateA" DataType="{x:Type local:SampleClassA}">
<StackPanel>
<TextBlock Text="{Binding Path=SampleProperty1}"></TextBlock>
<TextBlock Text="{Binding Path=SampleProperty2}"></TextBlock>
<TextBlock Text="{Binding Path=SamplePropertyA}"></TextBlock>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="myTemplateB" DataType="{x:Type local:SampleClassB}">
<StackPanel>
<TextBlock Text="{Binding Path=SampleProperty1}"></TextBlock>
<TextBlock Text="{Binding Path=SampleProperty2}"></TextBlock>
<TextBlock Text="{Binding Path=SamplePropertyB}"></TextBlock>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="myTemplateBase" DataType="{x:Type local:SampleClass}">
<StackPanel>
<TextBlock Text="{Binding Path=SampleProperty1}"></TextBlock>
<TextBlock Text="{Binding Path=SampleProperty2}"></TextBlock>
</StackPanel>
</DataTemplate>
<local:SampleDataTemplateSelector x:Key="myBindPropertyTemplateSelector"
TemplateA="{StaticResource myTemplateA}"
TemplateB="{StaticResource myTemplateB}"
SampleClassBaseTemplate="{StaticResource myTemplateBase}" />
</Window.Resources>
<Grid>
<ContentControl Content="{Binding BindProperty}" ContentTemplateSelector="{StaticResource myBindPropertyTemplateSelector}" />
</Grid>
</Window>
MainWindow.xaml.vb
Class MainWindow
Dim myBindProperty As SampleClass
Public ReadOnly Property BindProperty As SampleClass
Get
Return myBindProperty
End Get
End Property
Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs)
myBindProperty = New SampleClassA()
DataContext = Me
End Sub
End Class
Public Class SampleClass
Public Property SampleProperty1 As String = "Class SampleClass Property1"
Public Property SampleProperty2 As String = "Class SampleClass Property2"
End Class
Public Class SampleClassA
Inherits SampleClass
Public Property SamplePropertyA As String = "Class SampleClassA"
End Class
Public Class SampleClassB
Inherits SampleClass
Public Property SamplePropertyB As String = "Class SampleClassB"
End Class
Public Class SampleDataTemplateSelector
Inherits DataTemplateSelector
Public Property TemplateA As DataTemplate
Public Property TemplateB As DataTemplate
Public Property SampleClassBaseTemplate As DataTemplate
Public Overrides Function SelectTemplate(item As Object, container As DependencyObject) As DataTemplate
If item Is Nothing Then Return SampleClassBaseTemplate
If item.GetType.Equals(GetType(SampleClassA)) Then
Return TemplateA
End If
If item.GetType.Equals(GetType(SampleClassB)) Then
Return TemplateB
End If
Return SampleClassBaseTemplate
End Function
End Class
Upvotes: 4