2010-10-01 33 views
7

我能够使用一个ItemsControl内一个ItemTemplate来呈现特定格式的项目。但是,如果ItemsControl中的某个项目碰巧是一个TextBox,那么将显示该TextBox而不是ItemsTemplate的一个实例。从我所知道的情况来看,对于任何FrameworkElement来说都是如此。这是一个ItemsControl的预期行为,还是我做错了什么?为什么ItemsControl不使用我的ItemTemplate?

一个例子:

<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,集合中的每个项目都会呈现为模板的一个实例。但是,在这种情况下,将呈现以下内容:蓝色矩形,后面是文本框,后面是蓝色矩形,后面是红色矩形。

+0

我猜,这是预期的行为,并旨在让开发人员能够添加特殊的一次性使用控件。例如,我可能会使用它将Button添加到清除选择的ComboBox,或者我可能会将TextBox放入ListBox中,以过滤由ItemsSource指定的集合。我很想听到有人对此行为有一些正式答案,因为我发现它与ItemTemplate的使用不直观。 – Drew 2010-10-01 21:44:01

+0

安东尼的好问题和很好的答案,谢谢你们。 – Golvellius 2013-11-27 16:22:03

回答

12

ItemsControl具有从项集合传递的对象,并返回true如果该对象可以被直接添加到项目面板而不产生的容器(和由此模板)受保护构件IsItemItsOwnContainerOverride

基实现对于从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

截至2015年,他们可能已经修复了第二部分。使用.NET 4.5.1中的WPF,如果我为'IsItemItsOwnContainerOverride'返回'false',那么模板似乎在项目容器上设置。 – 2015-05-18 21:51:54

2

我只是推测这里,但我敢打赌,它的行为的ItemContainerGenerator内居住。我打赌,ItemContainerGenerator着眼于一个项目,如果它是一个UIElement它说,“冷静,一直在产生该项目的容器,我就回吧”,如果它不是,它说,“我最好生成这个物品的一个容器,DataTemplate在哪里?“

相关问题