根据项目类型和视图选项切换 ListBox ItemTemplate

发布于 2024-10-16 04:32:46 字数 1240 浏览 5 评论 0原文

我目前正在 WPF 中实现一个列表框,其项目有 2 种替代布局:

,我已经使用 DataTriggerListBox 切换 ItemTemplate 来完成此操作,并且运行良好:

<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 的精神吗?

谢谢。

I'm currently implementing a listbox in WPF that will have 2 alternative layouts for its items:

Alternative list item styles of wrapping icons and detailed tiles

So far, I've done this using a DataTrigger to switch the ItemTemplate for the ListBox and it's working well:

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

However, the Runs collection to which the list is bound will also contain different types of object:

interface IRunItem
{
  // ...
}

class CompletedRunItem : IRunItem
{
  // ...
}

class PendingRunItem : IRunItem
{
  // ...
}

Each of the object types should have its own 'tile' and 'icon' templates (making 4 templates in total). What's the best way of switching on these two properties to according to the boolean ShowRunsAsIcons and the type of the list item?

I've considered using a pair of DataTemplateSelector subclasses -- one to choose between tile templates based on item type, and one to choose between icon templates based on item type -- but this just feels horribly clunky. I feel as though I should be taking advantage of WPF's ability to choose the correct template based on the object's type, but in this instance, I don't see how to combine that with the list's different view options.

Any ideas of how to do this that's more in the spirit of WPF?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

迷爱 2024-10-23 04:32:46

尽管我不相信这是最好的答案,但我已经改变了我的方法来利用 WPF 的自动模板选择。我现在为每个具体数据类定义了“顶级”数据模板。

这些数据模板只包含一个 ContentControl,其 ContentTemplate 属性通过 DataTrigger 设置,绑定到数据上下文的 ShowRunsAsIcons 属性。

例如,下面是 PendingRunItem 的无键数据模板:

<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 或两个。

Although I'm not convinced it's the best answer, I've changed my approach to take advantage of WPF's automatic template selection. I now have 'top-level' data templates defined for each of my concrete data classes.

These data templates contain nothing but a ContentControl whose ContentTemplate property is set via a DataTrigger, binding to the data context's ShowRunsAsIcons property.

As an example, here's the keyless data template for PendingRunItem:

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

The icon and tile representations for the relevant classes are then just regular data templates. And the ListBox no longer needs its Style property defined:

<ListBox ItemsSource="{Binding Runs}" SelectedItem="{Binding SelectedRun}"/>

I'd be interested to know people's thoughts on this approach and its benefits and drawbacks when compared to using a DataTemplateSelector or two.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文