2010-11-10 14 views
6

Wygląda na to, że spowodowanie, że ContentPresenter w moim ListBoxItem.ContentTemplate powoduje awarię programu Visual Studio?Czy jest jakiś problem z ContentPresenter w ListBoxItem.ContentTemplate?

<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> 

A może używam ContentPresenter źle? Zasadniczo chcę tekst powitania, świat, aby przejść do tych prezenterów zawartości

+1

Próbowałem swój kod i rozbił w porządku :) –

+2

Nie można używać ContentPresenter w ContentTemplate ponieważ jest to rodzaj kodu rekurencyjnego, ContentPresenter będzie ponownie załadować ContentTemplate i ContentTemplate będzie ponownie załadować ContentPresenter i tak dalej .. .. –

Odpowiedz

8

ItemTemplate z ListBox jest kopiowany do ContentTemplate z ListBoxItem podczas generowania interfejsu użytkownika. Oznacza to, że twój kod jest równoważny z poniższym.

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

Dodaje się jednak elementy ListBoxItems, więc nie jest to prawda w 100%.
(ItemTemplate i ItemTemplateSelector są ignorowane przedmiotów już Spośród ItemsControl typ kontenera; type = '') ListBoxItem

Aby rozwinąć dlaczego awarii Visual Studio. Po pierwsze, zawiesza się tylko wtedy, gdy pole ListBox jest zapełniane, więc stanie się to tylko przy dodawaniu ListBoxItem bezpośrednio do Xaml (Twoja aplikacja nadal będzie ulegać awarii, ale nie będzie to VS). ContentPresenter to miejsce, w którym Szablon dla ListBox wstawia ContentTemplate. Więc jeśli mamy ten

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

i nie zmienić szablon tak to wygląda mniej więcej tak (wersja shortend)

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

Otrzymamy

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

i tak dalej . To nigdy się nie kończy, a Visual Studio ulega awarii. Jeśli zmienimy szablon na ten , nie dojdzie do awarii, ponieważ ContentPresenter nigdy nie jest używany.
(Domyślam się, że rozbiłem Studio kilkanaście razy podczas wypróbowywania tego :)

W twoim przypadku powinieneś użyć szablonu zamiast 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>