2010-08-10 29 views
2

J'ai une ObservableCollection liée à un objet DataGrid WPFToolkit dans un modèle MVVM. Toutes les 30 secondes, j'ai un thread d'arrière-plan qui interroge un service pour certaines données. Quand il revient, il le monte dans le thread d'interface utilisateur et met à jour ObservableCollection en appelant d'abord Clear() sur la collection, puis en appelant Add() pour chaque élément. Lorsque cela se produit, les données sont mises à jour correctement à l'écran, cependant, le DataGrid scintille. Comment puis-je empêcher cela?La mise à jour d'une ObservableCollection dans WPF provoque un scintillement d'écran; Comment puis-je l'empêcher?

Répondre

1

Il semble que vous remplacez simplement toutes vos données si vous effacer puis en ajoutant chaque élément un à la fois. Au lieu de réutiliser votre ObservableCollection, pouvez-vous simplement définir la source d'éléments de votre grille de données sur une nouvelle ObservableCollection avec vos nouveaux éléments?

+0

C'était tout. Je pensais que réutiliser la collection était la bonne façon d'éviter le scintillement, mais il s'avère que votre suggestion est la bonne façon! Merci! –

+0

Pas de problème. Le scintillement que je crois a été provoqué lorsque vous avez effacé ObservableCollection ... Ainsi, le DataGrid est passé de plein de vieilles données, à vide (le scintillement), puis rechargé lorsque vous avez ajouté les nouveaux éléments. Maintenant, vous allez simplement rempli de données anciennes, à remplir de nouvelles données ... pas d'état vide entre les deux. – Scott

+1

Je déteste quand la technique que j'utilise pour éviter un problème est la technique qui cause le problème. –

2

J'ai créé une solution simple mais puissante maximale pour votre problème:

public class MyCollection<T> : ObservableCollection<T> 
{ 
    private bool _isInEditMode = false; 

    public void BeginEdit() 
    { 
     _isInEditMode = true; 
    } 

    public void CommitEdit() 
    { 
     _isInEditMode = false; 
     OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 
    } 

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) 
    { 
     if (_isInEditMode == false) 
     { 
      base.OnCollectionChanged(e); 
     } 
    } 
} 

La ma classe de collection empêche collection a changé des événements pendant que vous êtes en mode d'édition. Lancez "BeginEdit" avant de supprimer les éléments. Ensuite, ajoutez vos nouveaux objets. Lorsque vous avez terminé, utilisez "CommitEdit" et l'affichage ne sera actualisé qu'une seule fois.

Si je l'ai testé avec une simple liste, où j'ajoute 1.000.000 éléments de chaîne. Essayez ceci. C'est drôle :)

private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     MyCollection<string> list = testBox.ItemsSource as MyCollection<string>; 
     //list.BeginEdit(); 
     for (int i = 0; i < 1000000; i++) 
     { 
      list.Add("test " + i); 
     } 
     list.CommitEdit(); 

    } 

Supprimez le // de list.BeginEdit() et voyez la différence. Il est environ 15 secondes sur < 1 seconde.

Salutations,

Jan

+0

Désolé, cela n'a pas résolu le problème. Le scintillement était toujours là. Heureusement, se lier simplement à une nouvelle collection résout chaque fois le problème. –

+0

Ah d'accord, c'est dommage que cela ne fonctionne pas pour datagrids. Je n'ai pas testé. Avec d'autres ItemsControls, cela fonctionne très bien. Bien sûr, la solution avec une nouvelle liste est beaucoup plus simple, si vous remplacez toujours toute la liste. – JanW

+0

J'ai créé une extension similaire à la collection observable pour ajouter une méthode AddRange comme les autres collections ont. Je n'ai jamais remarqué un scintillement, mais je ne fais qu'ajouter des lots d'objets, ne jamais faire un full clear ... –