Dot Net Luchador
Dot Net Luchador

Reputation: 103

Not all ListBoxItem are created equal

In the example below, the DataTemplate only gets applied to the first and second list item, the third and fourth are completely ignored.

<ListBox>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Button Content="{Binding}"></Button>
        </DataTemplate>
    </ListBox.ItemTemplate>
    <sys:String>One</sys:String>
    <sys:String>Two</sys:String>
    <ListBoxItem>Three</ListBoxItem>
    <ListBoxItem>Four</ListBoxItem>
</ListBox>

My question is why?

If I look at the output window, I see the following error: “ItemTemplate and ItemTemplateSelector are ignored for items already of the ItemsControl's container type; Type='ListBoxItem'.

So I get why my templates are not being applied, but why does WPF gets all nasty with me when I explicitly use ListBoxItems objects on my list items? I mean, WPF is implicitly hosting ALL items on a ListBoxItems object so why can’t WPF just thank me for doing some of the work that it is supposed to do rather than throwing the error? :)

Thank you.

Upvotes: 1

Views: 889

Answers (1)

Jay
Jay

Reputation: 57919

It sounds more like a warning than error -- just filling you in on why your declared ItemTemplate and ListBoxItems aren't going to work together.

edit

In response to your comment, consider the following:

    <ListBox>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Button Content="{Binding}" />
            </DataTemplate>
        </ListBox.ItemTemplate>
        <ListBox.Items>
            <System:String>One</System:String>
            <System:String>Two</System:String>
            <ListBoxItem Background="Red">Three</ListBoxItem>
            <ListBoxItem>
                <ListBoxItem.Template>
                    <ControlTemplate>
                        <Button Content="{Binding Content, RelativeSource={RelativeSource TemplatedParent}}" 
                                Background="Blue"
                                Foreground="White"
                                />
                    </ControlTemplate>
                </ListBoxItem.Template>
                <ListBoxItem.Content>
                    Four
                </ListBoxItem.Content>
            </ListBoxItem>
        </ListBox.Items>
    </ListBox>

Think of the ItemTemplate as defining a way to display the item type. For items "One" and "Two", which are strings, the ItemTemplate defines how to display that and wraps the result in a ListBoxItem.

If, however, an item is already a ListBoxItem

  1. This is not an item that the ItemTemplate can necessarily deal with because an ItemTemplate is a DataTemplate, and
  2. The ListBoxItem can define its own properties, style, and template.

So, if you are explicitly creating ListBoxItems, I think it is better that WPF respect the ability to customize the styling of that item, rather than overriding it all with the ItemTemplate.

That's the beauty of using ItemTemplates -- you can use them, mix, match, and mangle them, usually without really having to worry about ListBoxItem. The only time I've ever had to deal with ListBoxItem directly is when I create a style for it -- declaring one as an item explicitly is probably a rare case at best.

Upvotes: 2

Related Questions