我目前正在WPF中实现一个列表框,它的项目有两个替代布局:
到目前为止,我已使用DataTrigger
为ItemTemplate
切换ListBox
,并且效果很好:
<ListBox ItemsSource="{Binding Runs}" SelectedItem="{Binding SelectedRun}">
<ListBox.Style>
<Style TargetType="ListBox">
<Setter Property="ItemTemplate" Value="{StaticResource tileTemplate}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ShowRunsAsIcons}" Value="True">
<Setter Property="ItemTemplate" Value="{StaticResource iconTemplate}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.Style>
</ListBox>
但是,列表绑定到的Runs
集合还将包含不同的类型对象:
interface IRunItem
{
// ...
}
class CompletedRunItem : IRunItem
{
// ...
}
class PendingRunItem : IRunItem
{
// ...
}
每个对象类型都应该有自己的“tile”和“icon”模板(共计4个模板)。根据布尔ShowRunsAsIcons
和列表项的类型,将这两个属性切换为最佳方法是什么?
我考虑过使用一对DataTemplateSelector
子类 - 一个用于根据项目类型选择切片模板,另一个用于根据项目类型在图标模板之间进行选择 - 但这只是感觉非常笨重。我觉得我应该利用WPF根据对象的类型选择正确的模板的能力,但在这个例子中,我没有看到如何将它与列表的不同视图选项结合起来。
关于如何做到这一点的任何想法更符合WPF的精神?
感谢。
答案 0 :(得分:1)
虽然我不相信这是最好的答案,但我已经改变了我的方法,以利用WPF的自动模板选择。我现在为每个具体数据类定义了“顶级”数据模板。
这些数据模板只包含ContentControl
ContentTemplate
属性,DataTrigger
属性是通过PendingRunItem
设置的,绑定到数据上下文的ShowRunsAsIcons属性。
例如,这是<DataTemplate DataType="{x:Type Common:PendingRunItem}">
<ContentControl Content="{Binding}">
<ContentControl.Style>
<Style TargetType="ContentControl">
<Setter Property="ContentTemplate" Value="{StaticResource pendingTileTemplate}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding DataContext.ShowRunsAsIcons, RelativeSource={RelativeSource FindAncestor, AncestorType=ListBox}}" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource pendingIconTemplate}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</DataTemplate>
的无密钥数据模板:
ListBox
相关类的图标和图块表示只是常规数据模板。并且Style
不再需要定义<ListBox ItemsSource="{Binding Runs}" SelectedItem="{Binding SelectedRun}"/>
属性:
DataTemplateSelector
与使用{{1}}或者两个{{1}}相比,我有兴趣了解人们对这种方法及其优点和缺点的看法。