2009-10-10 7 views
2

J'ai un contrôle qui étend PropertyGrid qui permet aux utilisateurs de définir les propriétés de certains de mes objets de programme. Ces objets ont un événement qui est déclenché lorsque l'une de leurs propriétés est modifiée et le PropertyGrid s'abonne à cet événement pour qu'il se rafraîchisse automatiquement lorsqu'une propriété est modifiée. Mon problème se produit lorsqu'un grand nombre d'objets est sélectionné et l'utilisateur définit une propriété sur tous les objets à la fois. Le contrôle est inondé de requêtes Refresh(), ce qui prend beaucoup de temps (par exemple, définir une propriété sur ~ 300 objets prend environ 20 secondes avec la fonction de rafraîchissement automatique activée, et juste une fraction de seconde lorsqu'elle est activée de). Je souhaite empêcher le gestionnaire d'événements d'actualiser la grille alors que la grille de propriétés est en train de définir une propriété, mais je n'ai malheureusement pas trouvé de moyen de déterminer quand la grille "démarre" et "arrête" la définition de la propriété. J'espérais qu'il y aurait des méthodes ou quelque chose que je pourrais passer outre, comme ...Comment déterminer quand un contrôle PropertyGrid est sur le point de modifier la propriété d'un objet

override void OnSetPropertyStart() 
{ 
    suppressRefresh = true; 
} 
override void OnSetPropertyEnd() 
{ 
    suppressRefresh = false; 
} 

Malheureusement, cela ne semble pas être le cas. Existe-t-il un autre moyen de déterminer quand la grille de propriétés définit une propriété ou d'obtenir le même effet?

Répondre

1

Le type est-il sous votre contrôle? Vous pourriez ajouter une paire d'événements FooUpdating/FooUpdated? Une autre option serait d'écrire un modèle de propriété personnalisé avec TypeDescriptionProvider, mais je suppose que ce serait beaucoup de travail. Ma première tentative serait un avant/après deux ...

Quelque chose comme (mis à jour pour afficher 3.5 approche, voir l'histoire pour un exemple 2.0):

class MyType : INotifyPropertyChanged, INotifyPropertyChanging 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    public event PropertyChangingEventHandler PropertyChanging; 

    protected void UpdateField<T>(ref T field, T newValue, string propertyName) 
    { 
     if (!EqualityComparer<T>.Default.Equals(field, newValue)) 
     { 
      OnPropertyChanging(propertyName); 
      field = newValue; 
      OnPropertyChanged(propertyName); 
     } 
    } 
    protected void OnPropertyChanged(string propertyName) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) handler(this, 
      new PropertyChangedEventArgs(propertyName)); 
    } 
    protected void OnPropertyChanging(string propertyName) 
    { 
     PropertyChangingEventHandler handler = PropertyChanging; 
     if (handler != null) handler(this, 
      new PropertyChangingEventArgs(propertyName)); 
    } 
    private string name; 

    public string Name 
    { 
     get { return name; } 
     set { UpdateField(ref name, value, "Name"); } 
    } 
    private DateTime dateOfBirth; 
    public DateTime DateOfBirth 
    { 
     get { return dateOfBirth; } 
     set { UpdateField(ref dateOfBirth, value, "DateOfBirth"); } 
    } 
} 

Ensuite, il suffit gérer les deux événements et activer/désactiver les mises à jour, le cas échéant.

+2

Sur .NET 3.5 ou version ultérieure, il serait préférable d'implémenter l'interface INotifyPropertyChanging définie par le framework plutôt que de créer un événement PropertyChanging personnalisé. Cela éviterait une prolifération inutile et jouerait sans doute mieux avec des fonctionnalités définies par le framework telles que la liaison de données. – itowlson

+0

Point très valide. Modification pour mettre à jour. –

+0

Merci pour votre réponse - Je vais voir combien d'effort cela prendrait (j'ai beaucoup de différents types d'objets avec beaucoup de propriétés que je devrais éditer pour faire cela). En attendant, j'ai résolu le problème en limitant les rafraîchissements PropertyGrid de sorte qu'ils ne peuvent se produire que toutes les 25 ms. Ceci est assez rapide pour que l'utilisateur ne s'en aperçoive pas, et semble résoudre le problème avec une tonne de requêtes Refresh() qui "s'empilent" tout à la fois. –

Questions connexes