我能够在ItemsControl中使用ItemTemplate以特定格式呈现项目。但是,如果ItemsControl中的一个项恰好是TextBox,则呈现TextBox而不是ItemsTemplate的实例。据我所知,任何FrameworkElement都是如此。这是ItemsControl的预期行为,还是我做错了什么?
一个例子:
<ItemsControl>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="5">
<Rectangle Fill="Blue" Height="20" Width="20" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.Items>
<sys:Object />
<TextBox />
<sys:Object />
<Rectangle Fill="Red" Height="20" Width="20" />
</ItemsControl.Items>
</ItemsControl>
我希望这能显示四个蓝色矩形。我认为只要定义了ItemTemplate,集合中的每个项目都会呈现为模板的一个实例。但是,在这种情况下,将呈现以下内容:蓝色矩形后跟TextBox,后跟蓝色矩形,后跟红色矩形。
答案 0 :(得分:13)
ItemsControl
有一个受保护的成员IsItemItsOwnContainerOverride
,它从items集合中传递一个对象,如果该对象可以直接添加到items面板而没有生成的容器,则返回true
(因此是模板化的。)
对于从UIElement
派生的任何对象,基本实现返回true。
要获得您期望的行为,您需要从ItemsControl
继承并覆盖此方法并使其始终返回false。不幸的是,这不是问题的结束。如果项目是PrepareContainerForItemOverride
,则ItemTemplate
的默认实现仍然不会将UIElement
分配给容器,因此您还需要覆盖此方法: -
protected override bool IsItemItsOwnContainerOverride(object item)
{
return false;
}
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
base.PrepareContainerForItemOverride(element, item);
((ContentPresenter)element).ContentTemplate = ItemTemplate;
}
答案 1 :(得分:2)
我只是在这里推测,但我敢打赌它的行为存在于ItemContainerGenerator
内部。我敢打赌,ItemContainerGenerator
看一个项目,如果它是UIElement
它说,“很酷,项目容器已生成,我只会返回它”,如果不是,它说,“我最好为这个项目生成一个容器。DataTemplate
?”