使用ContentTemplateSelector将DataTemplate绑定到ContentControl

时间:2014-09-10 16:39:55

标签: wpf data-binding binding datatemplate contentcontrol

我的Window.Resources中有3个DataTemplate,强类型为三个不同的类:

<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>

还有一点DataTemplateSelector:

<local:SampleDataTemplateSelector x:Key="myBindPropertyTemplateSelector"
    TemplateA="{StaticResource myTemplateA}"
    TemplateB="{StaticResource myTemplateB}" 
    SampleClassBaseTemplate="{StaticResource myTemplateBase}" />

显然有DataTemplateSelector类,名为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必须区分3个简单的类:SampleClass和2个派生类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

在我的窗口xaml中,ContentControl的设置如下:

<ContentControl Content="{Binding BindProperty}" ContentTemplateSelector="{StaticResource myBindPropertyTemplateSelector}" />

其中BindProperty是在窗口代码后面定义的属性:

Dim myBindProperty As SampleClass
Public ReadOnly Property BindProperty As SampleClass
    Get
        Return myBindProperty
    End Get
End Property

毕竟,在我的窗口Load事件中有BindProperty初始化

Private Sub Window_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
    myBindProperty = New SampleClassA()
End Sub

没有编译错误。在执行中,SampleDataTemplateSelector的SelectTemplate例程中的item参数永远不会,因此它无法选择正确的模板......并且不显示任何内容。我做错了什么?

1 个答案:

答案 0 :(得分:3)

我重新创建了你的项目,如果你将DataContext = Me添加到Window_Loaded,它确实有效。我将模板更改为使用StackPanel而不是Grid(因此文本块彼此不重叠)。 这是一个完整的工作版本:

enter image description here

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