tmytのらくがき

個人の日記レベルです

ItemsControlにFrameworkElementを並べたらItemTemplateが反映されない!

困りました。ItemsControlにFrameworkElementを並べたらItemTemplateが反映されず、FrameworkElement自身がUIに表示されてしまします。

<ItemsControl Margin="12" MaxHeight="160">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Border BorderBrush="SpringGreen" BorderThickness="1">
                <Button Content="aaa" />
            </Border>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <Rectangle Height="10" Fill="Tomato"/>
    <Rectangle Height="10" Fill="MediumTurquoise"/>
    <Rectangle Height="10" Fill="YellowGreen"/>
</ItemsControl>

これの結果がこれです。

f:id:tmyt:20150112224831p:plain

ちなみにListBoxでは期待したとおりにDataTemplateが反映されます。

<ListBox Margin="12" MaxHeight="160">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Border BorderBrush="SpringGreen" BorderThickness="1">
                <Button Content="aaa" />
            </Border>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <Rectangle Height="10" Fill="Tomato"/>
    <Rectangle Height="10" Fill="MediumTurquoise"/>
    <Rectangle Height="10" Fill="YellowGreen"/>
</ListBox>

f:id:tmyt:20150112224918p:plain

調べたところ、ItemsControlはItemがUI要素かどうかでItemsControl.IsItemItsOwnContainerOverrideの値をtrue or false に切り替えているようです。おそらくListBoxはfalse 決め打ちっぽいです。まぁ確かに前者のほうが挙動としては正のでしょうが…

ここを常にfalse を返すようにしたItemsControlの派生クラスを作ってみました。

public class HogeItems : ItemsControl
{
    protected override bool IsItemItsOwnContainerOverride(object item)
    {
        return false;
    }
}
<local:HogeItems Margin="12" MaxHeight="160">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Border BorderBrush="SpringGreen" BorderThickness="1">
                <Button Content="aaa" />
            </Border>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <Rectangle Height="10" Fill="Tomato"/>
    <Rectangle Height="10" Fill="MediumTurquoise"/>
    <Rectangle Height="10" Fill="YellowGreen"/>
</local:HogeItems>

f:id:tmyt:20150112225123p:plain

期待通りの結果になりました。