複数のタイプのビューモデルを含むObservableCollectionがあり、GridViewColumnの各CellTemplate内に各タイプのDataTemplateを作成したいと思います。この簡単な例では、ベースのViewModelを作成できますが、xamlからこれを実行できるようにしたいと思います。以下のxamlは、私がやろうとしていることを示しています。ここでは、DataTemplatesの1つが各CellTemplateに使用されます。
GridViewColumn.Resourcesがある場合は、そこにDataTemplatesを定義し、CellTemplateのContentPresenterでDataTemplateを使用しますが、明らかにそれはできません。 TemplateSelectorが必要かもしれないと思っていますが、どこから始めればよいかわかりません。
<ListView ItemsSource={Binding GenericObservableCollection>
<ListView.View>
<GridView>
<GridViewColumn Header="Type">
<GridViewColumn.CellTemplate>
<DataTemplate DataType="{x:Type vm:ActionInputViewModel}">
<TextBlock Text="Input"/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:ActionOutputViewModel}">
<TextBlock Text="Output"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Value">
<GridViewColumn.CellTemplate>
<DataTemplate DataType="{x:Type vm:ActionInputViewModel}">
<TextBlock Text="{Binding Property1}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:ActionOutputViewModel}">
<TextBlock Text="{Binding Property2}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
ここに行くにはいくつかの異なる方法があります。 DataTemplateSelectorを記述し、それをGridViewColumn.CellTemplateSelector
プロパティに割り当てることができます。
public class ViewModelTemplateSelector : DataTemplateSelector
{
public DataTemplate InputTemplate { get; set; }
public DataTemplate OutputTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
return (item is ActionInputViewModel) ? InputTemplate : OutputTemplate;
}
}
次に、すべてのテンプレートをリソースのどこかに移動できます。簡潔にするために、ここではリストビューに貼り付けています。
<ListView ItemsSource="{Binding GenericObservableCollection}">
<ListView.Resources>
<DataTemplate x:Key="InLabel" DataType="{x:Type vm:ActionInputViewModel}">
<TextBlock Text="Input"/>
</DataTemplate>
<DataTemplate x:Key="OutLabel" DataType="{x:Type vm:ActionOutputViewModel}">
<TextBlock Text="Output"/>
</DataTemplate>
<DataTemplate x:Key="InValue" DataType="{x:Type vm:ActionInputViewModel}">
<TextBlock Text="{Binding Property1}"/>
</DataTemplate>
<DataTemplate x:Key="OutValue" DataType="{x:Type vm:ActionOutputViewModel}">
<TextBlock Text="{Binding Property2}"/>
</DataTemplate>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn Header="Type">
<GridViewColumn.CellTemplateSelector>
<vm:ViewModelTemplateSelector InputTemplate="{StaticResource InLabel}" OutputTemplate="{StaticResource OutLabel}"/>
</GridViewColumn.CellTemplateSelector>
</GridViewColumn>
<GridViewColumn Header="Value">
<GridViewColumn.CellTemplateSelector>
<vm:ViewModelTemplateSelector InputTemplate="{StaticResource InValue}" OutputTemplate="{StaticResource OutValue}"/>
</GridViewColumn.CellTemplateSelector>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
または、すべてをXAMLで保持する場合は、DataTypesを使用して適切なテンプレートを解決できます。通常は、最も近いコンテナのResourcesコレクションに配置するだけですが、残念ながら、GridViewColumnはUI要素ではないため、Resourcesコレクションはありません。これを回避するには、独自の型付きテンプレートを保持できるセルごとにContentControlを追加します。
<ListView ItemsSource="{Binding GenericObservableCollection}">
<ListView.View>
<GridView>
<GridViewColumn Header="Type">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ContentControl Content="{Binding}">
<ContentControl.Resources>
<DataTemplate DataType="{x:Type vm:ActionInputViewModel}">
<TextBlock Text="Input"/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:ActionOutputViewModel}">
<TextBlock Text="Output"/>
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Value">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ContentControl Content="{Binding}">
<ContentControl.Resources>
<DataTemplate DataType="{x:Type vm:ActionInputViewModel}">
<TextBlock Text="{Binding Property1}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:ActionOutputViewModel}">
<TextBlock Text="{Binding Property2}"/>
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
どちらの方法でも同じ結果が得られるはずです。