2010-10-23 18 views
4

Disons que j'ai une collection d'objets de différentes classes. Chaque classe a son UserControl DataTemplated dans un fichier de ressources.Enveloppez quelque chose autour de chaque élément dans un ItemsControl

Maintenant, je veux utiliser ItemsControl pour afficher la collection, mais je veux une bordure ou un expandeur autour de chaque élément.

je me attends quelque chose comme cela fonctionne:

<ItemsControl ItemsSource="{Binding MyObjects}"> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <StackPanel Orientation="Horizontal"/> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <Border BorderBrush="Black" BorderThickness="3"> 
       <ContentPresenter/> 
      </Border> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 

Mais le ContentPresenter semble prendre ItemTemplate, parce que je reçois un débordement de pile.

Comment obtenir le DataTemplate de chaque élément dans ItemTemplate?

+0

Je pense que vous devez fournir quelques détails sur l'erreur que vous rencontrez. Est-ce que votre fenêtre de sortie fournit des indices? – benPearce

+0

J'ai un bouton qui ajoute un élément à MyObjects. Après je l'ai cliqué, il n'y a rien de nouveau dans la sortie. J'ai une System.StackOverflowException de WindowsBase.dll. Il n'y a pas de source disponible, il n'y a pas de démontage à me montrer, il n'y a pas de détails de l'exception elle-même. ("Impossible d'évaluer l'expression car le thread actuel est dans un état de débordement de pile"). La pile d'appel dans VS ne me donne rien. Mais si je supprime le ContentPresenter du ItemTemplate, je n'obtiens qu'une bordure vide pour chaque élément, sans débordement de pile. – Guge

Répondre

8

Normalement, vous pouvez envisager de le faire en modélisant le conteneur d'éléments. Le problème est le "générique" ItemsControl utilise le ContentPresenter comme son conteneur d'article. Ainsi, même si vous essayez de définir un style avec ItemContainerStyle, vous ne pourrez pas fournir de modèle car le ContentPresenter ne prend pas en charge le modèle de contrôle (il prend en charge la création de modèle de données mais ne sert à rien ici).

Pour utiliser un conteneur modèle vous devrez dériver de ItemsControl comme dans ce example.

Une alternative pourrait être simplement d'utiliser le contrôle ListBox à la place. Ensuite, vous pouvez simplement fournir un modèle personnalisé en définissant un modèle ListBoxItem via un style.

Vous pouvez en savoir plus sur les conteneurs here.

(Avec votre permissen j'ajoute la solution à votre réponse, Guge)

<ListBox ItemsSource="{Binding MyObjects}" Grid.Column="1"> 
     <ListBox.ItemsPanel> 
      <ItemsPanelTemplate> 
       <StackPanel Orientation="Horizontal"/> 
      </ItemsPanelTemplate> 
     </ListBox.ItemsPanel> 
     <ListBox.ItemContainerStyle> 
      <Style TargetType="{x:Type ListBoxItem}"> 
       <Setter Property="Template"> 
        <Setter.Value> 
         <ControlTemplate TargetType="{x:Type ListBoxItem}"> 
          <Border BorderBrush="Black" BorderThickness="3"> 
           <ContentPresenter/> 
          </Border> 
         </ControlTemplate> 
        </Setter.Value> 
       </Setter> 
      </Style> 
     </ListBox.ItemContainerStyle> 
    </ListBox> 
+0

Merci beaucoup. Parfois, je néglige le fait qu'un modèle peut faire partie d'un style. Il y a quelque chose de contre-intuitif, je l'espère seulement dans ma propre cavité crânienne. – Guge

+0

C'est contre-intuitif, au moins par rapport aux autres technologies! Ce qui revient à se rappeler que le style peut définir n'importe quelle propriété, et le modèle lui-même est juste une autre propriété (qui est la «magie» WPF). – Schneider