„Kolekcja elementów musi być pusta przed użyciem ItemsSource”.


172

Próbuję wyświetlić obrazy w widoku listy WPF w stylu WrapPanel, jak opisano w tym starym artykule zespołu ATC Avalon: Jak utworzyć widok niestandardowy .

Kiedy próbuję wypełnić ListView za pomocą zapytania LINQ-to-Entities kolekcji obiektów ADO.NET Entity Framework, otrzymuję następujący wyjątek:

Wyjątek

Kolekcja elementów musi być pusta przed użyciem ItemsSource.

Mój kod…

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>

Ustawiłem punkt przerwania na tej linii. ListViewImages.ItemsSourcejest Nothingtuż przed przypisaniem LINQ.

Odpowiedzi:


127

Powodem, dla którego ten szczególny wyjątek jest generowany, jest to, że zawartość elementu jest stosowana do kolekcji Items ListView. Dlatego XAML inicjuje ListView z pojedynczym lokalnym: ImageView w swojej kolekcji Items. Ale gdy używasz ItemsControl, musisz użyć właściwości Items lub właściwości ItemsSource, nie można używać obu w tym samym czasie. W związku z tym, gdy atrybut ItemsSource zostanie przetworzony, zostanie zgłoszony wyjątek.

Możesz dowiedzieć się, do której właściwości zostanie zastosowana zawartość elementu, wyszukując ContentPropertyAttribute w klasie. W tym przypadku jest to zdefiniowane wyżej w hierarchii klas, na ItemsControl:

[ContentPropertyAttribute("Items")]

Zamiarem było, aby widok ListView był ustawiony na lokalny: ImageView, więc poprawka polega na jawnym wskazaniu właściwości do ustawienia.

Napraw kod XAML, a wyjątek zniknie:

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

Brakowało tej <ListView.View>etykiety.


6
Ta odpowiedź jest poprawna. Ale zanim sprawdzisz ten przypadek, sprawdź, czy twój XAML jest poprawny, jak wspomniano w innych odpowiedziach. W przeciwnym razie możesz spędzić dużo czasu, patrząc na elementy ItemSource itp., Aby ostatecznie stwierdzić, że jest to spowodowane małą literówką.
pjm

182

Przez jakiś czas miałem ten sam błąd w nieco innym scenariuszu. miałem

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

który ustaliłem

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

15
Dziękuję Ci! Taki prosty problem ... ale taki zagmatwany błąd.
Scott

15
Dla mnie różnica polegała na tym, że po prostu brakowało <DataGrid.Columns> (a nawet nie korzystałem z wpftoolkit).
Dave,

1
Brakuje mi również <DataGrid.Columns>.
Eternal21

67

Właśnie natknąłem się na BARDZO podstępny przykład tego problemu. Mój oryginalny fragment był znacznie bardziej złożony, przez co trudno było dostrzec błąd.

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

Błąd? Dodatkowy > po pierwszym <ItemsControl>tagu otwierającym ! <Got zastosowane do wbudowanej w punktach zbiórki. Gdy DataContext został później ustawiony, natychmiastowy błąd crashola. Dlatego podczas debugowania tego problemu należy zwracać uwagę na więcej niż tylko błędy otaczające określone elementy potomne danych ItemsControl.


4
To samo spotkało mnie: Extra >=> Exception
surfen

7
oczywiście nie tylko to wystarczy. wszelkie przypadkowo wpisane znaki same staną się przedmiotami. możesz sprawdzić ten stan, tymczasowo usuwając atrybut ItemsSource. Jeśli nadal masz wiersze w siatce danych, musisz sprawdzić, czy nie ma obcych znaków
Simon_Weaver

4
Armentage ... właśnie mnie uratowałeś Nie wiem ile godzin tego szukałem !!! Dziękuję bardzo za opublikowanie tego ... głosowania!
John Fairbanks

1
Bardzo interesujące. Nie jestem pewien, dlaczego to nie jest błąd kompilacji. Mnie też dopadł!
shawn1874

1
Ojej, miałem ten sam błąd: Extra ">". Mogę ci kupić piwo? Co za dziwny błąd i jak trudno go znaleźć bez błędu kompilacji! To uratowało mi dzień!
Björn Grossmann

40

Ja też w innym scenariuszu.

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

Teraz, gdy uzupełnisz brakujący tag Control.ItemTemplate , wszystko wróci do normy:

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

1
Dlaczego WPF musi być tak cholernie nieoczywiste? Ustawienie DataTemplate dla ListBox spowodowało zabawne wyjątki, ale żaden z nich nie prowadził we właściwym kierunku.
Alois Kraus

Problem ten został naprawiony podczas korzystania z pliku <ItemsControl>.
RHaguiuda

27

Miałem ten sam błąd w innym scenariuszu

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

Rozwiązaniem było dodanie ItemsControl.ItemsPaneltagu przedItemsPanelTemplate

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

To rozwiązało mój problem!
RDV,

14

⚠️ Aby odpowiedzieć inaczej ⚠️

💡 W Xaml sprawdź, czy w zdefiniowanych obszarach nie ma brakujących węzłów nadrzędnych ani nieprawidłowych węzłów .

Na przykład

To się nie udaje:

Poniżej nie ma odpowiedniego rodzica dla ItemsPanelTemplatewęzła podrzędnego:

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

To działa:

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

💡 Podany jest właściwy węzeł nadrzędny <ItemsControl.ItemsPanel>^^^. 💡


2
To. Brakowało <DataGrid.Columns>i zawierało kolumny szablonów bezpośrednio w środku <DataGrid>. Dziwny błąd.
Andrew Grothe,

12

Wyjątek

Kolekcja elementów musi być pusta przed użyciem ItemsSource.

Ten wyjątek występuje, gdy dodajesz elementy do ItemsSource różnych źródeł . Dlatego upewnij się, że przypadkowo nie przegapiłeś tagu, nie zgubiłeś tagu, nie dodałeś dodatkowych tagów lub nie zapisałeś tagu.

<!--Right-->

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


<!--WRONG-->

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

Gdy ItemsControl.ItemsSourcejest już ustawiony Binding, inne elementy (Siatka, Przycisk, ...) nie mogą być dodawane do źródła. Jednak gdy nieItemsSource jest używany, dozwolony jest następujący kod :

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

zwróć uwagę na brakującą ItemsSource="{Binding MyItems}"część.


2
Coś w tym, co tu powiedziałeś, skłoniło mnie do dokładnego przyjrzenia się kolumnom siatki danych ... potem zdałem sobie sprawę, że nie ma ich w tagu datagrid.columns. +1 za danie mi mentalnego biegu.
Craig Brett


4

W moim przypadku był to tylko dodatkowy StackPanel wewnątrz 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>

Staje się:

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

i wszystko w porządku.


4

W moim przypadku nie używał DataTemplate dla ItemsControl.

Stary:

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

Nowy:

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

Powinienem podziękować za 4 godziny, czas, który spędziłem próbując naprawić ten bałagan ... DZIĘKUJĘ
Mark

4

Mój był w stylu datagrid. Jeśli pominiesz <DataGrid.RowStyle>tagi wokół stylu, pojawi się ten problem. Dziwne jest to, że tak to działało przez jakiś czas. Oto zły kod.

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

i dobre

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

3

Miałem ten sam błąd. Problem polegał na tym, że ten dodatkowy symbol „>” został dodany przez pomyłkę między tagami </ComboBox.SelectedValue> i </ComboBox>:

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

a oto poprawny kod:

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

2

Wystąpił ten błąd, gdy próbowałem zastosować menu kontekstowe do pliku TreeView. Te próby zakończyły się złym kodem XAML, który jakoś się skompilował:

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

Zwróć uwagę na problematyczną linię: ContextMenu=""> .
Nie wiem, dlaczego został skompilowany, ale doszedłem do wniosku, że warto o tym wspomnieć jako powód tej tajemniczej wiadomości o wyjątku. Jak powiedział Armentage, rozejrzyj się uważnie po XAML, szczególnie w miejscach, które niedawno edytowałeś.


2

Napotkałem ten błąd w innej sytuacji. Próbowałem zdefiniować styl dla TreeViewItems bezpośrednio w ramach <TreeView>, ale zamiast tego powinienem był osadzić go w<TreeView.ItemContainerStyle> .

Źle:

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

Poprawny:

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

1

Może nie taka użyteczna odpowiedź, ale miałem ten sam problem przy zmianie kolejności kolumn i popełniłem błąd jak w poniższym przykładzie. Mając dużo kolumn, zmieniłem ich kolejność i jakoś wkleiłem jedną po zamknięciu tagu /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>

Zresztą straciłem przez to pół godziny. Mam nadzieję, że to pomoże innym.


1

<ListView.View>Napotkałem ten problem, ponieważ w moim XAML brakowało jednego poziomu tagu .

Ten kod spowodował ten błąd.

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

Następujące rzeczy to naprawiły

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

-1

Uważaj na literówki! Miałem następujące

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

(Zwróć uwagę na tailing > , który jest interpretowany jako zawartość, więc ustawiasz podwójną zawartość ... Zajęło mi to chwilę :)


Armentage już o tym wspomniał, podając nieco więcej wyjaśnień.
Ben Voigt
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.