2009-06-11 4 views
0

Je transmets IEnumerable Collection dans WPF DataGrid via la propriété DataGrid.ItemSource. Mais il ne met pas à jour DataGrid lorsque j'essaie de modifier des éléments de collection dans un code. Pourquoi?WPF DataGrid.ItemSource

Répondre

3

Vous devez vous connecter à un type qui implémente l'interface INotifyCollectionChanged afin de fournir des événements que la liaison de données peut utiliser pour surveiller l'ajout ou la suppression d'éléments. Le meilleur type pour cela dans WPF est ObservableCollection <>, qui a un constructeur qui acceptera votre IEnumerable:

ObservableCollection<string> collection = new ObservableCollection<string>(iEnumerableobject); 
dataGrid.ItemSource = collection; 
collection.Add("Wibble"); 

mettra à jour correctement. De vos commentaires à l'autre réponse, il semble que vous deviez appeler l'appel d'ajout à l'intérieur du thread de l'interface utilisateur. Sans connaître votre code dans plus de détails, je ne sais pas pourquoi vous avez besoin de le faire, mais supposons que vous obtenez les données d'un service en arrière-plan:

private ObservableCollection<string> collection; 

public void SetupBindings() 
{ 
    collection = new ObservableCollection<string>(iEnumerableobject); 
    dataGrid.ItemSource = collection; 
    //off the top of my head, so I may have this line wrong 
    ThreadPool.Queue(new ThreadWorkerItem(GetDataFromService)); 
} 

public void GetDataFromService(object o) 
{ 
    string newValue = _service.GetData(); 

    //if you try a call add here you will throw an exception 
    //because you are not in the same thread that created the control 
    //collection.Add(newValue); 

    //instead you need to invoke on the Ui dispatcher 
    if(Dispather.CurrentDispatcher.Thread != Thread.CurrentThread) 
    { 
     Dispatcher.CurrentDispatcher.Invoke(() => AddValue(newValue)); 
    } 
} 

public void AddValue(string value) 
{ 
    //because this method was called through the dispatcher we can now add the item 
    collection.Add(value); 
} 

Comme je le dis, je ne avoir un IDE à portée de main, donc cela ne compilera probablement pas, mais vous pointera dans la bonne direction.

Selon la tâche exacte que vous effectuez en arrière-plan, il existe peut-être de meilleures façons de procéder. Mon exemple ci-dessus serait beaucoup plus facile à mettre en œuvre en utilisant un backgroundworker, donc vous voudrez peut-être lire sur cela aussi.

+0

+1 pour cette homme, et pas seulement pour l'utilisation de "Wibble" dans une réponse. Bravo, je dis! . . . et oui, je me sens un peu étrange cet après-midi. . . –

+0

J'ai changé pour ObservableCollection, mais cela ne fait toujours pas de différence. Il montre des données correctes quand je démarre un programme, mais ne met jamais à jour la grille après ... Je fais quelque chose de mal – Agzam

1

Vous devez utiliser ObservableCollection à la place. (Ou faire votre propre classe les enveloppes de collecte et de mettre en œuvre l'interface INotifyPropertyChanged)

+0

Quand j'essaye d'apporter des changements dans la collection, VS dit: Ce type de CollectionView ne supporte pas modifie son SourceCollection à partir d'un thread différent du thread Dispatcher. – Agzam

+0

Lorsqu'une collection est liée à l'interface graphique, vous pouvez uniquement apporter des modifications à la collection à partir du thread principal de l'interface graphique. Vous pouvez le faire en appelant Invoke sur le répartiteur de formulaires. Faites si (Dispather.CurrentDispatcher.Thread! = Thread.CurrentThread) {puis appelez Dispatcher.CurrentDispatcher.Invoke (et passez un délégué à votre méthode) Voir ici: http://msdn.microsoft.com/fr-fr/ library/system.windows.threading.dispatcher.invoke.aspx –

+0

Vous devez effectuer toutes vos mises à jour sur le thread de l'interface utilisateur, car WPF ne prend en charge que les contrôles de modification du thread sur lequel ils ont été créés. – Andy

0

Vous pouvez également utiliser une collection qui implémente l'interface INotifyCollectionChanged si vous ne pouvez pas utiliser ObservableCollection pour une raison quelconque ...