2009-07-02 5 views
1

Comment puis-je empêcher le déclenchement de plusieurs événements du même type déclenchés par une seule action?Empêcher les événements de se déclencher plusieurs fois à partir d'une seule action

Par exemple, j'ai un ListView contenant certains éléments. Lorsque je sélectionne ou désélectionne tous les éléments, l'événement SelectedIndexChanged est déclenché une fois pour chaque élément. Au contraire, j'aimerais recevoir une indication d'événement unique sur l'action de l'utilisateur (sélection/désélection d'éléments), quel que soit le nombre d'éléments.

Y a-t-il un moyen d'y parvenir?

+0

(répondu à un commentaire) –

Répondre

3

Vous ne pouvez pas modifier le code ListView et le sous-classement ne fournit pas beaucoup d'options.

Je suggère que vous ajoutiez simplement un petit délai (200ms ou similaire) à votre code - c'est-à-dire que vous ne faites que le calcul un peu après la dernière mise à jour. Quelque chose comme:

using System; 
using System.Windows.Forms; 
static class Program { 
    [STAThread] 
    static void Main() { 
     Application.EnableVisualStyles(); 
     ListView list; 
     TextBox txt; 
     Timer tmr = new Timer(); 
     tmr.Interval = 200; 
     Form form = new Form { 
      Controls = { 
       (txt = new TextBox { Dock = DockStyle.Fill, Multiline = true}), 
       (list = new ListView { Dock = DockStyle.Right, View = View.List, 
        Items = { "abc", "def" , "ghi", "jkl", "mno" , "pqr"}}) 
      } 
     }; 
     list.SelectedIndexChanged += delegate { 
      tmr.Stop(); 
      tmr.Start(); 
     }; 
     tmr.Tick += delegate { 
      tmr.Stop(); 
      txt.Text += "do work on " + list.SelectedItems.Count + " items" 
       + Environment.NewLine; 
     }; 
     Application.Run(form); 
    } 
} 
+0

Un exemple serait très apprécié :) –

+0

Je vois, mais cette approche n'empêche pas l'exécution mais la reporte. Ce que je cherche est d'exécuter une fois et abandonner toutes les autres exécutions inutiles.Dès que quelque chose est sélectionné ou désélectionné, je mets à jour une variable qui contient l'état global de la sélection qui doit être fait exactement une fois par action de l'utilisateur. –

+0

Vous devez supprimer les actions ** plus tôt ** - sinon vous ne savez pas que vous agissez sur les bonnes données. Le code affiché laisse tomber tout sauf le dernier. En tant que tel, il n'exécute en effet qu'une seule action par utilisateur. –

1

Seulement en arrivant au problème d'une direction légèrement différente. Par exemple. souscrire une perte de concentration. En fin de compte, l'application ou le moteur d'exécution ne peut pas déclencher un événement sur "toutes les modifications de sélection effectuées" sans utiliser autre chose car l'application ne peut pas prédire si l'utilisateur effectuera un autre clic sur le contrôle. conserve la concentration.

Même en utilisant le focus, l'utilisateur peut revenir à ce contrôle.

+0

désélection tous les articles se fait par un simple clic en arrière-plan de la ListView, mais l'événement se déclenche pour chaque élément décochée néanmoins, ce qui se traduit par une mauvaise performance en tant que le calcul qui ne doit se produire qu'une fois par sélection/désélection est exécuté pour chaque élément à la place du changement de sélection. –

+0

@Michael: pourquoi ne pas vous abonner aux événements click, et dans l'événement click lire l'ensemble actuel des éléments sélectionnés? – Richard

+0

Bonne idée, je l'ai essayé et ça marche plutôt bien en performance. Seul inconvénient est, lorsque vous cliquez sur l'arrière-plan de l'événement ListView aucun clic est déclenché, ce qui signifie que je dois trouver un autre moyen d'effacer une autre vue. Peut-être que je laisserai la compensation dans l'événement SelectedIndexChanged. –

0

Si votre ListView est dans virtual mode, vous pouvez utiliser le VirtualItemsSelectionRangeChanged event. Cet événement sera déclenché une seule fois pour l'action de l'utilisateur (sélection/désélection).

+0

Qu'est-ce que le mode virtuel implique? Jamais vraiment entendu parler de ça. Sur MSDN il indique "Pour utiliser le mode virtuel, vous devez gérer l'événement RetrieveVirtualItem (...)". Dois-je fournir d'autres fonctionnalités pour que ListView virtuel fonctionne comme les ListViews non virtuelles auxquelles je suis habitué? –

+0

"Mode virtuel" signifie que les ListViewItems ne sont pas créés en même temps pour tous les éléments, mais uniquement sur demande, uniquement pour les éléments actuellement visibles. Le mode virtuel est particulièrement utile si vous avez de grandes quantités de données à afficher et si vous stockez les données ailleurs dans votre application en plus de ListView. Donc, fondamentalement, les deux différences sont de stocker les données pour les éléments par vous-même et de gérer l'événement RetrieveVirtualItem. – EFrank

Questions connexes