2011-05-04 5 views
8

J'ai une application WPF et la conception suit le modèle MVVM standard.Les contrôles de base de données ne doivent pas être mis à jour s'ils ne sont pas visibles

Lorsque les données sous-jacentes sont modifiées, mon modèle de vue déclenche l'événement PropertyChanged afin que les contrôles puissent être mis à jour.

Ma vue principale est un contrôle onglet, de sorte que la majorité des contrôles sont invisibles à la fois. Il y a des problèmes de performance, et j'ai réalisé qu'une grande partie du temps CPU est dédié à la récupération des données pour mettre à jour les contrôles invisibles. (Mon modèle de vue utilise l'évaluation paresseuse, donc il déclenche les événements PropertyChanged, mais ne calcule pas réellement les propriétés affichables finales jusqu'à ce que demandé).

Est-ce que WPF dispose d'un moyen standard pour résoudre ce problème? En théorie, si un contrôle invisible reçoit un événement PropertyChanged pertinent, il devrait simplement penser "Je dois requery cette propriété une fois que je suis à nouveau visible".

+0

Je ne pense pas qu'il existe, serait très utile cependant. –

Répondre

1

Je ne pense pas qu'il existe une infrastructure pour gérer les liaisons de désactivation associées à des contrôles non visibles. Malheureusement, il y a beaucoup de situations dans lesquelles vous voudriez un contrôle qui n'est pas visible pour participer à la liaison de données. Plus important encore, vous avez souvent un contrôle dont la visibilité dépend elle-même d'une liaison. En outre, vous pouvez avoir une liaison entre les propriétés d'un contrôle visible et un contrôle non visible. Ou quelqu'un voudra peut-être exactement le contraire de ce que vous voulez: le contrôle se peuplera tout en n'étant pas visible, puis ressortira complètement peuplé une fois visible.

Je pense que la seule bonne solution pour votre situation est d'éviter d'avoir des contrôles non visibles de poids lourds, si cela est possible. Spécifiquement pour votre contrôle de tabulation, j'aurais pensé que ce serait le comportement par défaut, mais peut-être que cela dépend de votre situation. Ironiquement, certaines personnes se plaignent que le TabControl détruit ses enfants lors de la commutation entre les onglets et aimerait savoir comment éviter cela parce que garder tous les onglets en arrière-plan prend du travail. Mais vous semblez avoir le problème inverse.

Pour référence, voici la source je l'ai mentionné pour TabControl enfants:

Vous pourriez être en mesure de faire quelques expériences dans un petit projet pour « allumer » le comportement de recyclage ils essaient d'éteindre. Si votre contrôle était chargé à la demande, le changement d'onglet pourrait être un peu plus lent, mais les performances sur un onglet s'amélioreraient.

+0

Pour des raisons héritées, il s'agit en fait d'un contrôle onglet WinForms, avec un certain nombre d'onglets contenant des contrôles WPF via ElementHost. Mon problème peut ne pas être représentatif du comportement de contrôle de tabulation habituel. –

+0

Aussi, merci de fournir un excellent contre-argument à la prémisse du titre. (J'expérimente des titres litigieux pour voir s'ils obtiennent plus de lectures :-). –

+0

Question intéressante. J'espère que vous avez trouvé une solution. Dans mon cas, votre stratégie a fonctionné. :-) –

1

Nous avons fait quelque chose le long de ces lignes dans notre ViewModel de base ..

note, vous devez au gel/dégel correspondant à la visibilité de la vue.

Il piège fondamentalement tous les événements PropertyChanged alors qu'il est gelé, et les repousse lorsqu'il est décongelé. Tout en ne gardant pas dupes, car ils n'ont pas d'importance dans notre cas.

public abstract class ViewModelBase : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    private readonly HashSet<string> hashSet = new HashSet<string>(); 
    private bool isFrozen; 

    protected void RaisePropertyChanged(string propertyName) 
    { 
     if (isFrozen) 
     { 
      lock (hashSet) 
      { 
       hashSet.Add(propertyName); 
       return; 
      } 
     } 

     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    protected void Freeze() 
    { 
     isFrozen = true; 
    } 

    /// <summary> 
    /// Enable PropertyChanged Events to fire again 
    /// </summary> 
    protected void Thaw(bool fireQueued) 
    { 
     isFrozen = false; 
     if (fireQueued) 
     { 
      lock (hashSet) 
      { 
       PropertyChangedEventHandler handler = PropertyChanged; 
       if (handler != null) 
       { 
        foreach (string propertyName in hashSet) 
        { 
         handler(this, new PropertyChangedEventArgs(propertyName)); 
        } 
       } 

       hashSet.Clear(); 
      } 
     } 
     else 
     { 
      hashSet.Clear(); 
     } 
    } 
} 
0

Mon modèle de vue de base possède une propriété IsVisible. Lorsque le modèle de vue est invisible, supprimez simplement les notifications modifiées de la propriété. Quand il devient visible éteindre une propriété a changé l'événement pour chaque propriété (pr passe en null au nom de la propriété)

Questions connexes