Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any problem with having a ContentPresenter in ListBoxItem.ContentTemplate?

It seems like having a ContentPresenter in my ListBoxItem.ContentTemplate is causing Visual Studio to crash?

<ListBox>
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="ContentTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <DockPanel>
                            <TextBlock><ContentPresenter /></TextBlock>
                        </DockPanel>
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ListBox.ItemContainerStyle>
    <ListBoxItem Content="Hello" />
    <ListBoxItem Content="World" />
</ListBox>

Or maybe I am using ContentPresenter wrong? Basically, I want the text hello, world to go into those content presenters

like image 550
Jiew Meng Avatar asked Nov 10 '10 13:11

Jiew Meng


1 Answers

The ItemTemplate of a ListBox is copied to the ContentTemplate of a ListBoxItem during UI generation. Meaning that your code is equivalent to the following.

<ListBox>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <DockPanel>
                <TextBlock><ContentPresenter /></TextBlock>
            </DockPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
    <ListBoxItem Content="Hello" />
    <ListBoxItem Content="World" />
</ListBox>

However, you're adding the ListBoxItems directly so this is not 100% true.
(ItemTemplate and ItemTemplateSelector are ignored for items already of the ItemsControl's container type; Type='ListBoxItem')

To elaborate on why Visual Studio crashes. First, it only crashes once the ListBox is being populated so this will only happend when adding ListBoxItem's directly in Xaml (Your app will still crash but not VS). The ContentPresenter is the place where the Template for the ListBox is inserting the ContentTemplate. So if we have this

<Style TargetType="ListBoxItem">           
    <Setter Property="ContentTemplate">           
        <Setter.Value>           
            <DataTemplate>           
                <TextBlock><ContentPresenter /></TextBlock>
            </DataTemplate>           
        </Setter.Value>           
    </Setter>           
</Style>

and we don't change the Template so it looks something like this (shortend version)

<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="ListBoxItem">
            <ContentPresenter/>
        </ControlTemplate>
    </Setter.Value>
</Setter>

We will get

<ContentPresenter/> -> <TextBlock><ContentPresenter /></TextBlock> ->
<TextBlock><TextBlock><ContentPresenter /></TextBlock></TextBlock>  

and so on. It never stops, and Visual Studio crashes. If we change the Template to this

<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="ListBoxItem">
            <TextBlock Text="No ContentPresenter Here"/>
        </ControlTemplate>
    </Setter.Value>
</Setter>

we get no crash since the ContentPresenter is never used.
(Think I crashed Studio a dozen times while trying this out :)

So in your case, you should use Template instead of ContentTemplate.

<ListBox>
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListBoxItem}">
                        <DockPanel>
                            <TextBlock><ContentPresenter /></TextBlock>
                        </DockPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ListBox.ItemContainerStyle>
    <ListBoxItem Content="Hello" />
    <ListBoxItem Content="World" />
</ListBox>
like image 76
Fredrik Hedblad Avatar answered Oct 22 '22 22:10

Fredrik Hedblad