"La collection d'éléments doit être vide avant d'utiliser ItemsSource."

172

J'essaie d'obtenir des images à afficher dans un WPF ListView stylé comme un WrapPanel, comme décrit dans cet ancien article de l'équipe ATC Avalon: Comment créer une vue personnalisée .

Lorsque j'essaie de remplir le ListView avec une collection interrogée LINQ-to-Entities d'objets ADO.NET Entity Framework, j'obtiens l'exception suivante:

Exception

La collection Items doit être vide avant d'utiliser ItemsSource.

Mon code…

Visual Basic

Private Sub Window1_Loaded(...) Handles MyBase.Loaded
    ListViewImages.ItemsSource = From g In db.Graphic _
                                 Order By g.DateAdded Ascending _
                                 Select g
End Sub

XAML

<ListView Name="ListViewImages"
          SelectionMode="Single"
          ItemsSource="{Binding}">
    <local:ImageView />
</ListView>

J'ai mis un point d'arrêt sur cette ligne. ListViewImages.ItemsSourceest Nothingjuste avant l'affectation LINQ.

Zack Peterson
la source

Réponses:

127

La raison pour laquelle cette exception particulière est levée est que le contenu de l'élément est appliqué à la collection Items de ListView. Ainsi, le XAML initialise le ListView avec un seul local: ImageView dans sa collection Items. Mais lorsque vous utilisez un ItemsControl, vous devez utiliser la propriété Items ou la propriété ItemsSource, vous ne pouvez pas utiliser les deux en même temps. Par conséquent, lorsque l'attribut ItemsSource est traité, une exception est levée.

Vous pouvez savoir à quelle propriété le contenu d'un élément sera appliqué en recherchant ContentPropertyAttribute sur la classe. Dans ce cas, il est défini plus haut dans la hiérarchie des classes, sur le ItemsControl:

[ContentPropertyAttribute("Items")]

L'intention ici était que la vue de ListView soit définie sur local: ImageView afin que le correctif indique explicitement la propriété à définir.

Corrigez le XAML et l'exception disparaît:

<ListView Name="ListViewImages"
          SelectionMode="Single"
          ItemsSource="{Binding}">
    <ListView.View>
        <local:ImageView />
    </ListView.View>
</ListView>

Il manquait cette <ListView.View>étiquette.

Dave
la source
6
Cette réponse est correcte. Mais avant de vérifier ce cas, vérifiez que votre xaml est correct, comme mentionné dans d'autres réponses. Sinon, vous pouvez passer beaucoup de temps à regarder les articles, etc. de ItemSource pour finalement découvrir que cela est causé par une petite faute de frappe.
pjm
182

J'ai eu cette même erreur pendant un certain temps dans un scénario légèrement différent. j'ai eu

<wpftoolkit:DataGrid
    AutoGenerateColumns="False"
    ItemsSource="{Binding Path=Accounts}" >
    <wpftoolkit:DataGridTextColumn 
        Header="Account Name" 
        Binding="{Binding Path=AccountName}" />
</wpftoolkit:DataGrid>

que j'ai fixé pour être

<wpftoolkit:DataGrid
    AutoGenerateColumns="False"
    ItemsSource="{Binding Path=Accounts}" >
    <wpftoolkit:DataGrid.Columns>
        <wpftoolkit:DataGridTextColumn 
            Header="Account Name" 
            Binding="{Binding Path=AccountName}" />
    </wpftoolkit:DataGrid.Columns>
</wpftoolkit:DataGrid>
Kenwarner
la source
15
Je vous remercie! Un problème si simple ... mais une erreur si déroutante.
Scott
15
Pour moi, la différence était simplement de manquer le <DataGrid.Columns> (et je n'utilisais même pas le wpftoolkit).
Dave
1
Manque le <DataGrid.Columns> pour moi aussi.
Eternal
67

Je viens de tomber sur un exemple TRÈS insidieux de ce problème. Mon fragment d'origine était beaucoup plus complexe, ce qui rendait difficile de voir l'erreur.

   <ItemsControl           
      Foreground="Black"  Background="White" Grid.IsSharedSizingScope="True"
      x:Name="MyGrid" ItemsSource="{Binding}">
      >
      <ItemsControl.ItemsPanel>
           <!-- All is fine here -->
      </ItemsControl.ItemsPanel>
      <ItemsControl.ItemTemplate>
           <!-- All is fine here -->
      </ItemsControl.ItemTemplate>
      <!-- Have you caught the error yet? -->
    </ItemsControl>

L'insecte? Le supplément > après la <ItemsControl>balise d' ouverture initiale ! Le <got appliqué à la collection Items intégrée. Lorsque le DataContext a été défini ultérieurement, crashola instantané. Recherchez donc plus que de simples erreurs entourant vos enfants de données spécifiques ItemsControl lorsque vous déboguez ce problème.

Armentage
la source
4
La même chose m'est arrivée: Extra >=> Exception
surfen
7
bien sûr, ce n'est pas seulement> cela fera cela. tous les caractères tapés accidentellement deviendront des éléments par eux-mêmes. vous pouvez vérifier cette condition en supprimant temporairement votre attribut ItemsSource. Si vous avez encore des lignes dans la grille de données, vous devez vérifier les caractères superflus
Simon_Weaver
4
Armentage ... tu viens de me sauver je ne sais pas combien d'heures de recherche pour ça !!! Merci beaucoup d'avoir publié ceci ... votez!
John Fairbanks
1
Très intéressant. Je ne sais pas pourquoi ce n'est pas une erreur de compilation. Ça m'a eu aussi!
shawn1874
1
Oh mon Dieu, j'ai eu la même erreur: Extra ">". Puis-je vous acheter une bière? Quelle étrange erreur et quelle difficulté à trouver sans erreur de compilation! Cela m'a sauvé la journée!
Björn Grossmann
40

Moi aussi sur un scénario différent.

<ComboBox Cursor="Hand" DataContext="{Binding}"  
              FontSize="16" Height="27" ItemsSource="{Binding}" 
              Name="cbxDamnCombo" SelectedIndex="0" SelectedValuePath="MemberId">

        <DataTemplate>
            <TextBlock DataContext="{Binding}">
                <TextBlock.Text>
                  <MultiBinding StringFormat="{}{0} / {1}">
                    <Binding Path="MemberName"/>
                    <Binding Path="Phone"/>
                  </MultiBinding>
                </TextBlock.Text>
            </TextBlock>
        </DataTemplate>

</ComboBox>

Maintenant, lorsque vous avez terminé avec la balise manquante Control.ItemTemplate , tout redevient normal:

<ComboBox Cursor="Hand" DataContext="{Binding}"  
              FontSize="16" Height="27" ItemsSource="{Binding}" 
              Name="cbxDamnCombo" SelectedIndex="0" SelectedValuePath="MemberId">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock DataContext="{Binding}">
                <TextBlock.Text>
                  <MultiBinding StringFormat="{}{0} / {1}">
                    <Binding Path="MemberName"/>
                    <Binding Path="Phone"/>
                  </MultiBinding>
                </TextBlock.Text>
            </TextBlock>
        </DataTemplate>
    <ComboBox.ItemTemplate>
</ComboBox>
Junior Mayhé
la source
1
Pourquoi WPF doit-il être si peu évident? La définition du DataTemplate pour un ListBox a provoqué des exceptions amusantes, mais aucune d'entre elles ne menait dans la bonne direction.
Alois Kraus
Cela m'a résolu lors de l'utilisation d'un fichier <ItemsControl>.
RHaguiuda
27

J'ai eu cette même erreur dans un scénario différent

<ItemsControl ItemsSource="{Binding TableList}">
    <ItemsPanelTemplate>
        <WrapPanel Orientation="Horizontal"/>
    </ItemsPanelTemplate>
</ItemsControl>

La solution était d'ajouter la ItemsControl.ItemsPanelbalise avant leItemsPanelTemplate

<ItemsControl ItemsSource="{Binding TableList}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>
ehudbk
la source
C'est ce qui a résolu mon problème!
RDV
14

⚠️ Pour énoncer la réponse différemment ⚠️

💡 Dans Xaml, vérifiez qu'il n'y a pas de nœuds parents manquants ou de nœuds incorrects dans les zones définies.

Par exemple

Ceci échoue:

Il n'y a pas de parent approprié pour le nœud enfant ci-dessous:ItemsPanelTemplate

<ItemsControl ItemsSource="{Binding TimeSpanChoices}">
    <ItemsPanelTemplate>
        <UniformGrid Rows="1" />
    </ItemsPanelTemplate>
    ...
</ItemsControl>

Cela fonctionne:

<ItemsControl ItemsSource="{Binding TimeSpanChoices}">
    <ItemsControl.ItemsPanel> <!-- I am the missing parent! -->
        <ItemsPanelTemplate>
            <UniformGrid Rows="1" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    ...    
</ItemsControl>

💡 Il existe un nœud parent approprié de <ItemsControl.ItemsPanel>fourni ^^^. 💡

ΩmegaMan
la source
2
Ce. Manquait <DataGrid.Columns>et contenait des colonnes de modèle directement à l'intérieur <DataGrid>. Erreur étrange pour cela.
Andrew Grothe
12

Exception

La collection Items doit être vide avant d'utiliser ItemsSource.

Cette exception se produit lorsque vous ajoutez des éléments aux ItemsSource sources via différentes . Assurez-vous donc de ne pas avoir accidentellement manqué une balise, égaré une balise, ajouté des balises supplémentaires ou mal écrite une balise.

<!--Right-->

<ItemsControl ItemsSource="{Binding MyItems}">
     <ItemsControl.ItemsPanel.../>
     <ItemsControl.MyAttachedProperty.../>
     <FrameworkElement.ActualWidth.../>
</ItemsControl>


<!--WRONG-->

<ItemsControl ItemsSource="{Binding MyItems}">
     <Grid.../>
     <Button.../>
     <DataTemplate.../>
     <Heigth.../>
</ItemsControl>

Tant que ItemsControl.ItemsSourceest déjà défini Binding, d'autres éléments (Grille, Bouton, ...) ne peuvent pas être ajoutés à la source. Cependant, tant qu'il ItemsSourcen'est pas utilisé, le code suivant est autorisé :

<!--Right-->
<ItemsControl>
     <Button.../>
     <TextBlock.../>
     <sys:String.../>
</ItemsControl>

remarquez la ItemsSource="{Binding MyItems}"pièce manquante .

Bizhan
la source
2
Quelque chose dans ce que vous avez dit ici m'a incité à jeter un long regard sur mes colonnes de grille de données ... puis j'ai réalisé qu'elles n'étaient pas dans une balise datagrid.columns. +1 pour me donner le jogging mental.
Craig Brett
4

Dans mon cas, c'était juste un StackPanel supplémentaire à l'intérieur de ListView:

<ListView Name="_details" Margin="50,0,50,0">
            <StackPanel Orientation="Vertical">
                <StackPanel Orientation="Vertical">
                    <TextBlock Text="{Binding Location.LicenseName, StringFormat='Location: {0}'}"/>
                    <TextBlock Text="{Binding Ticket.Employee.s_name, StringFormat='Served by: {0}'}"/>
                    <TextBlock Text="{Binding Ticket.dt_create_time, StringFormat='Started at: {0}'}"/>
                    <Line StrokeThickness="2" Stroke="Gray" Stretch="Fill" Margin="0,5,0,5" />
                    <ItemsControl ItemsSource="{Binding Items}"/>
                </StackPanel>
            </StackPanel>
        </ListView>

Devient:

<ListView Name="_details" Margin="50,0,50,0">
                <StackPanel Orientation="Vertical">
                    <TextBlock Text="{Binding Location.LicenseName, StringFormat='Location: {0}'}"/>
                    <TextBlock Text="{Binding Ticket.Employee.s_name, StringFormat='Served by: {0}'}"/>
                    <TextBlock Text="{Binding Ticket.dt_create_time, StringFormat='Started at: {0}'}"/>
                    <Line StrokeThickness="2" Stroke="Gray" Stretch="Fill" Margin="0,5,0,5" />
                    <ItemsControl ItemsSource="{Binding Items}"/>
                </StackPanel>
        </ListView>

et tout va bien.

Carl
la source
4

Dans mon cas, il n'utilisait pas de DataTemplate pour ItemsControl.

Vieux:

<ItemsControl Width="243" ItemsSource="{Binding List, Mode=TwoWay}">
    <StackPanel Orientation="Horizontal">
        <TextBox Width="25" Margin="0,0,5,0" Text="{Binding Path=Property1}"/>
        <Label Content="{Binding Path=Property2}"/>
    </StackPanel>
</ItemsControl>

Nouveau:

<ItemsControl Width="243" ItemsSource="{Binding List, Mode=TwoWay}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBox Width="25" Margin="0,0,5,0" Text="{Binding Path=Property1}"/>
                <Label Content="{Binding Path=Property2}"/>
            </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
Samiz
la source
Je devrais vous remercier 4 heures, le temps que j'ai passé à essayer de réparer ce gâchis ... MERCI
Marc
4

Le mien était avec un style datagrid. Si vous omettez les <DataGrid.RowStyle>balises autour du style, vous obtenez ce problème. Ce qui est étrange, c'est que cela a fonctionné pendant un moment comme ça. Voici le mauvais code.

 <DataGrid Name="DicsountScheduleItemsDataGrid"
                  Grid.Column="0"
                  Grid.Row="2"
                  AutoGenerateColumns="false"
                  ItemsSource="{Binding DiscountScheduleItems, Mode=OneWay}">
            <Style TargetType="DataGridRow">
                <Setter Property="IsSelected"
                        Value="{Binding IsSelected, Mode=TwoWay}" />
            </Style>

et le bon

 <DataGrid Name="DicsountScheduleItemsDataGrid"
                  Grid.Column="0"
                  Grid.Row="2"
                  AutoGenerateColumns="false"
                  ItemsSource="{Binding DiscountScheduleItems, Mode=OneWay}">
            <DataGrid.RowStyle>
            <Style TargetType="DataGridRow">
                <Setter Property="IsSelected"
                        Value="{Binding IsSelected, Mode=TwoWay}" />
            </Style>
            </DataGrid.RowStyle>
PatFromCanada
la source
3

J'ai eu la même erreur. Le problème était ce symbole supplémentaire ">" ajouté par erreur entre les balises </ComboBox.SelectedValue> et </ComboBox>:

<ComboBox 
   ItemsSource="{Binding StatusTypes}"
   DisplayMemberPath="StatusName"
   SelectedValuePath="StatusID">
   <ComboBox.SelectedValue>
      <Binding Path="StatusID"/>
   </ComboBox.SelectedValue>
   >
</ComboBox>

et voici le bon code:

<ComboBox 
   ItemsSource="{Binding StatusTypes}"
   DisplayMemberPath="StatusName"
   SelectedValuePath="StatusID">
   <ComboBox.SelectedValue>
      <Binding Path="StatusID"/>
   </ComboBox.SelectedValue>
</ComboBox>
Vladimir Trifonov
la source
2

J'ai eu cette erreur lorsque j'ai essayé d'appliquer des menus contextuels à mon TreeView. Ces essais ont abouti à un mauvais XAML qui s'est compilé d'une manière ou d'une autre:

<TreeView Height="Auto" MinHeight="100"  ItemsSource="{Binding Path=TreeNodes, Mode=TwoWay}" 
    ContextMenu="{Binding Converter={StaticResource ContextMenuConverter}}">
    ContextMenu="">
    <TreeView.ItemContainerStyle>
    ...  

Notez la ligne problématique: ContextMenu="">.
Je ne sais pas pourquoi il a été compilé, mais j'ai pensé que cela méritait d'être mentionné comme raison de ce message d'exception cryptique. Comme Armentage l'a dit, regardez attentivement le XAML, en particulier dans les endroits que vous avez récemment modifiés.

Noich
la source
2

J'ai rencontré cette erreur dans une autre situation. J'ai essayé de définir un style pour TreeViewItems directement dans le <TreeView>, mais j'aurais plutôt dû l'intégrer à l'intérieur <TreeView.ItemContainerStyle>.

Faux:

<TreeView ItemsSource="{Binding ExampleListView}">
    <Style TargetType="{x:Type TreeViewItem}">
        <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
        <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
    </Style>
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding SubItemListList}">
        ...
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

Correct:

<TreeView ItemsSource="{Binding ExampleListView}">
    <TreeView.ItemContainerStyle>
        <Style TargetType="TreeViewItem">
            <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
            <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
        </Style>
    </TreeView.ItemContainerStyle>
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding SubItemListList}">
        ...
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>
RonnyR
la source
1

Peut-être pas une réponse si utile, mais j'ai eu le même problème lors de la modification de l'ordre des colonnes et j'ai fait une erreur comme celle de l'exemple suivant. Ayant beaucoup de colonnes, je les ai réorganisées et en ai collé une après avoir fermé la balise /DataGrid.Columns:

       <DataGridTemplateColumn x:Name="addedDateColumn" Header="Added Date" Width="SizeToHeader">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Path=AddedDate}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
            <DataGridTemplateColumn x:Name="rowguidColumn" Header="rowguid" Width="SizeToHeader">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Path=rowguid}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
    </DataGrid>

Quoi qu'il en soit, perdu une demi-heure à cause de cela. J'espère que cela aide les autres.

Andrei Floroiu
la source
1

J'ai rencontré ce problème car un niveau de balise, <ListView.View>pour être spécifique, manquait dans mon XAML.

Ce code a produit cette erreur.

<Grid>
    <ListView Margin="10" Name="lvDataBinding" >
        <GridView>
            <GridViewColumn Header="Name" Width="120" DisplayMemberBinding="{Binding Name}" />
            <GridViewColumn Header="Age" Width="50" DisplayMemberBinding="{Binding Age}" />
            <GridViewColumn Header="Mail" Width="150" DisplayMemberBinding="{Binding Mail}" />
        </GridView>
    </ListView>
</Grid>

Ce qui suit l'a corrigé

<Grid>
    <ListView Margin="10" Name="lvDataBinding" >
        <ListView.View> <!-- This was missing in top! -->
            <GridView>
                <GridViewColumn Header="Name" Width="120" DisplayMemberBinding="{Binding Name}" />
                <GridViewColumn Header="Age" Width="50" DisplayMemberBinding="{Binding Age}" />
                <GridViewColumn Header="Mail" Width="150" DisplayMemberBinding="{Binding Mail}" />
            </GridView>
        </ListView.View>
    </ListView>
</Grid>
zar
la source
-1

Attention aux fautes de frappe! J'ai eu ce qui suit

<TreeView ItemsSource="{Binding MyCollection}">
    <TreeView.Resources>
        ...
    </TreeView.Resouces>>
</TreeView>

(Remarquez le tailing > , qui est interprété comme du contenu, vous définissez donc deux fois le contenu ... Cela m'a pris du temps :)

ElGauchooo
la source
Armentage l'a déjà mentionné, avec un peu plus d'explications.
Ben Voigt