2010-10-01 34 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在哪裏?「

相關問題