【问题标题】:Wrap something around each item in an ItemsControl在 ItemsControl 中围绕每个项目包装一些东西
【发布时间】:2010-10-23 11:19:07
【问题描述】:

假设我有一组不同类的对象。每个类在资源文件中都有其 UserControl DataTemplated。

现在我想使用 ItemsControl 来显示集合,但我希望每个项目周围都有一个 Border 或 Expander。

我希望这样的事情能够奏效:

<ItemsControl ItemsSource="{Binding MyObjects}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Border BorderBrush="Black" BorderThickness="3">
                <ContentPresenter/>
            </Border>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

但是 ContentPresenter 似乎选择了 ItemTemplate,因为我遇到了堆栈溢出。

如何在 ItemTemplate 中获取每个 Item 的 DataTemplate?

【问题讨论】:

  • 我认为您需要提供一些有关您遇到的错误的详细信息。您的输出窗口是否提供任何线索?
  • 我有一个向 MyObjects 添加项目的按钮。单击它后,Output 中没有任何新内容。我从 WindowsBase.dll 得到一个 System.StackOverflowException。没有可用的来源,没有反汇编可以向我展示,也没有异常本身的详细信息。 (“无法评估表达式,因为当前线程处于堆栈溢出状态”)。 VS 中的调用堆栈没有给我任何东西。但是,如果我从 ItemTemplate 中删除 ContentPresenter,我只会得到每个项目的空边框,没有堆栈溢出。

标签: wpf datatemplate itemscontrol itemtemplate


【解决方案1】:

通常您可以考虑通过模板化项目容器来执行此操作。问题是“通用”ItemsControl 使用ContentPresenter 作为其项目容器。因此,即使您尝试使用ItemContainerStyle 设置样式,您也会发现您无法提供模板,因为ContentPresenter 不支持控件模板(它支持数据模板但在这里没有用处)。

要使用模板容器,您必须从 ItemsControl 派生,就像在这个 example 中一样。

替代方法可能只是使用ListBox 控件。然后,您可以通过样式设置ListBoxItem 模板来提供自定义模板。

您可以阅读有关容器的更多信息here

(在您的允许下,我将解决方案添加到您的答案中,Guge)

    <ListBox ItemsSource="{Binding MyObjects}" Grid.Column="1">
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal"/>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
        <ListBox.ItemContainerStyle>
            <Style TargetType="{x:Type ListBoxItem}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ListBoxItem}">
                            <Border BorderBrush="Black" BorderThickness="3">
                                <ContentPresenter/>
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </ListBox.ItemContainerStyle>
    </ListBox>

【讨论】:

  • 非常感谢。我有时会忽略模板可以是样式的一部分。有一些违反直觉的东西,希望只在我自己的颅腔内。
  • 这是违反直觉的,至少与其他技术相比!归根结底是要记住 Style 可以设置任何属性,而 Template 本身只是另一个属性(这是 WPF 的“魔法”)。
【解决方案2】:

我只会做以下事情:

<ItemsControl.ItemTemplate>
    <DataTemplate>
        <Border BorderBrush="Black" BorderThickness="3">
            <ContentControl Content={Binding} />
        </Border>
    </DataTemplate>
</ItemsControl.ItemTemplate>

由于DataTemplate标签内的数据上下文是源集合中的一个项目,我们可以使用ContentControl来显示这个项目。 {Binding} 表示我们正在绑定到整个数据上下文。您项目的所有DataTemplates 都将被隐式应用,就像我们没有指定ItemsControl.ItemTemplate一样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-26
    • 2013-01-09
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    相关资源
    最近更新 更多