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

Zack Peterson
źródło

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.

Dave
źródło
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>
kenwarner
źródło
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.

Armentage
źródło
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>
Junior Mayhé
źródło
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>
ehudbk
źródło
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>^^^. 💡

ΩmegaMan
źródło
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ęść.

Bizhan
źródło
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.

Carl
źródło
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>
samiz
źródło
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>
PatFromCanada
źródło
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>
Vladimir Trifonov
źródło
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ś.

Noich
źródło
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>
RonnyR
źródło
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.

Andrei Floroiu
źródło
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>
zar
źródło
-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ę :)

ElGauchooo
źródło
Armentage już o tym wspomniał, podając nieco więcej wyjaśnień.
Ben Voigt