我有一个ObservableCollection,它包含多个类型的视图模型,我想在每个GridViewColumn的CellTemplates中为每个类型创建一个DataTemplate。在这个简单的例子中,我可以创建一个基本的ViewModel,但我希望能够从xaml中完成这个。下面的xaml显示了我想要做的事情,其中一个DataTemplates将用于每个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>
答案 0 :(得分:33)
你可以在这里找到几种不同的方式。您可以编写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中:
<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>
无论哪种方式都应该给你相同的结果。