web-dev-qa-db-fra.com

L'opération n'est pas valide tant que ItemsSource est en cours d'utilisation. Accéder à des éléments et les modifier avec ItemsControl.ItemsSource à la place

Je suis nouveau dans Binding et WPF j'ai récemment appris à créer une listBox à plusieurs colonnes à l'aide de la technologie Binding.

 <ListView ItemsSource="{Binding Items}" Margin="306,70,22,17" MouseDoubleClick="listBoxSS_MouseDoubleClick" Name="listBoxSS" >           
    <ListView.View>
            <GridView>
                <GridView.Columns>
                    <GridViewColumn Header="first_name " Width="100" DisplayMemberBinding="{Binding Path=First_name}" />
                    <GridViewColumn Header="last_name" Width="100" DisplayMemberBinding="{Binding Path=Last_name}" />
                    <GridViewColumn Header="phone_number" Width="100" DisplayMemberBinding="{Binding Path=Phones[0]}" />
                    <GridViewColumn Header="notes" Width="100" DisplayMemberBinding="{Binding Path=Notes}" />
                </GridView.Columns>
            </GridView>
        </ListView.View>
    </ListView>

et voici le code: 

List<Student> arr = search.students();
        listBoxSS.ItemsSource = arr;

mais le problème était quand j'ai essayé d'utiliser ajouter ou supprimer un élément ou effacer 

 listBoxSS.Items.Clear();

S'il vous plaît, j'ai besoin d'un exemple d'utilisation de la source des éléments ou de la manière dont je peux ajouter, supprimer ou effacer la liste.

MODIFIER:

<ListView ItemsSource="{Binding Items}" Margin="306,70,22,17" MouseDoubleClick="listBoxSS_MouseDoubleClick" Name="listBoxSS" >
    <ListView.View>
        <GridView>
            <GridView.Columns>
                <GridViewColumn Header="first_name " Width="100" DisplayMemberBinding="{Binding Path=First_name}" />
                <GridViewColumn Header="last_name" Width="100" DisplayMemberBinding="{Binding Path=Last_name}" />
                <GridViewColumn Header="phone_number" Width="100" DisplayMemberBinding="{Binding Path=Phones[0]}" />
                <GridViewColumn Header="notes" Width="100" DisplayMemberBinding="{Binding Path=Notes}" />
            </GridView.Columns>
        </GridView>
    </ListView.View>
</ListView>

et voici le code: 

 ObservableCollection<Employee> Gemployees;
var employees = new ObservableCollection<Employee>(search.employees());

search.employees() obtenir la liste de tous les employés de ma base de données

 listBoxPE.ItemsSource = employees;
        Gemployees = employees;

maintenant je peux effectuer toutes les méthodes sur Gemployees

 Gemployees.Remove((Student)listBoxSS.SelectedItem);
 Gemployees.Add((Student)listBoxSS.SelectedItem);

La ListView effectue un rafraîchissement à chaque fois que j'ajoute ou supprime un élément de Gemployees !! Cool mais toujours un peu de travail difficile sur la liaison. Maintenant, je fais une classe d'interface pour chaque ListView afin que je puisse y mettre mes données. Il n'effectuera aucune flexibilité dans l'ajout d'éléments. 

20
Yasser

Vous liez la ItemsSource à une propriété de la DataContext appelée Items. Pour mettre à jour la collection, vous devez accéder à la propriété Items dans la DataContext et l'effacer.

De plus, la propriété Items doit être de type ObservableCollection et non pas List si vous souhaitez qu'elle mette à jour l'interface utilisateur chaque fois que la collection sous-jacente est modifiée.

Votre morceau de code qui définit la ItemsSource dans le code derrière n'est pas nécessaire et doit être supprimé. Il vous suffit de définir la ItemsSource à un endroit, pas les deux.

Voici un exemple simple de la façon dont cela peut fonctionner:

// Using Students instead of Items for the PropertyName to clarify
public ObservableCollection<Student> Students { get; set; }

public MyConstructor()
{
    ...

    Students = search.students();
    listBoxSS.DataContext = this;
}

Maintenant, quand vous avez:

<ListView ItemsSource="{Binding Students}" ... />

vous liez la ItemsSource au ObservableCollection<Student> et, lorsque vous souhaitez effacer la liste, vous pouvez appeler:

Students.Clear()
28
Rachel

Bizarre mais vrai: les frappes de touches erronées suivantes dans mon fichier XAML ont généré l'erreur "L'opération n'est pas valide tant que ItemsSource est en cours d'utilisation. Accédez aux éléments et modifiez-les avec ItemsControl.ItemsSource."

</ItemsControl.ItemTemplate>x`

Notez les caractères "x`" après la balise d’élément de fermeture.

13
Brett

Je sais que cette question a reçu une réponse il y a environ 2 ans. Cependant, j’avais moi aussi ce problème et j’ai pensé à une solution possible, ce qui fonctionne. Peut-être que cela ne fonctionne pas dans certains scénarios et peut-être que je ne vois tout simplement pas quelque chose, mais cela a fonctionné pour moi, alors je le partage ici:

listView.ClearValue(ItemsControl.ItemsSourceProperty);
listView.ItemsSource = NewSource;

J'espère sincèrement que cela aidera quelqu'un.

9
Matthijs H

Vous devez utiliser la collection liée aux données de votre ItemsSource. Afin d’obtenir des notifications de changement de collection (lorsque des éléments sont ajoutés ou supprimés), vous devez utiliser un ObservableCollection<T> :

var students = new ObservableCollection<Student>(search.students());
listBoxSS.ItemsSource = students;

students.Clear();
students.Add(new Student("ABC"));

Et vous devriez supprimer la déclaration ItemsSource="{Binding Items}" de votre XAML.

3
Douglas

Je suis au courant de la soirée mais je pense que cette réponse n’est pas très claire ci-dessus. Cela est lié à la publication de personnages non autorisés, mais cela provoque également l'exception:

<ItemsControl ItemsSource="{Binding AnObservableCollection}">
    <Label Content="{Binding Name}"/>
</ItemsControl>

Quand ce que vous vouliez dire était:

<ItemsControl ItemsSource="{Binding AnObservableCollection}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <Label Content="{Binding Name}"/>
            </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

C’est facile comme un nouveau venu (ou avant le premier café du matin) de penser que le premier est correct et que l’exception n’explique aucunement ce qui ne va pas.

3
Tim Rutter

Affectez la propriété ItemsSource de la liste à une propriété publique de la classe du formulaire. Ensuite, essayez d’ajouter une suppression, appelant PropertyChanged à l’intérieur du sélecteur, au lieu d’appeler clear directement sur la source d’éléments de la listbox.

1
Josh

J'avais le même problème et je me suis finalement rendu compte que j'essayais d'ajouter un nouvel élément directement à ItemsSource du contrôle, plutôt qu'à ObservableCollection qui servait d'élément. 

Je pensais que je posterais ceci, car cela pourrait aider d’autres novices.

0
Travis

Le même message d'erreur est apparu suite à une erreur de syntaxe. Il s’est avéré que je définissais accidentellement un élément dans une TreeView qui avait une ItemsSource définie. J'avais défini un DataTemplate pour la vue arborescente, mais je l'ai accidentellement placé directement dans <TreeView> au lieu de <TreeView.Resources>, ce qui a provoqué l'erreur.

Ce que j'avais

<TreeView ItemSource ="{Binding Items}">
  <HierarchicalDataTemplate> ... </HierarchicalDataTemplate>
  <DataTemplate> ... </DataTemplate>
</TreeView>

Ce que j'aurais dû avoir:

<TreeView ItemSource ="{Binding Items}">
  <TreeView.Resources>
    <HierarchicalDataTemplate> ... </HierarchicalDataTemplate>
    <DataTemplate> ... </DataTemplate>
  </TreeView.Resources>
</TreeView>
0
Andrew Case