2011-08-19 2 views
0

Please see mockup code hereEventToCommand - comment empêcher les appels récursifs/rentrante lors de la manipulation SelectionChanged

Je crée une page de recherche interactif qui va chercher les données que les critères d'entrées utilisateur. Pour faire une histoire courte, j'ai plusieurs combos dont l'événement SelectionChanged est géré par EventToCommand.

EventToCommand appelle une méthode sur mon ViewModel qui, entre autres choses, modifie l'élément sélectionné pour plusieurs zones de liste déroulante. Bien sûr, cela déclenche EventToCommand et le processus se produit encore ... et encore ... et encore ....

Ma question est, est-il un moyen de faire la liaison à EventToCommand vraiment OneWayToSource de sorte qu'une mise à jour de la source ne déclenche pas l'événement?

+0

Etes-vous capable de faire quelque chose comme: Lorsque vous cliquez sur ComboBox, dans la commande target, définissez un type de drapeau; puis quand la récursivité revient à la commande, vérifiez le drapeau. Désolé pour le run-on, phrases incomplètes. –

Répondre

0

Méthode 1 ci-dessous montre une illustration peut-être utile d'une technique, mais la plupart des applications sera probablement mieux servi par la méthode 2.

Méthode 1

En tant que première approche, je pris l'approche suggérée par jberger . Cependant, puisque je m'appuie sur les valeurs contenues dans les arguments d'événement, et je veux maintenir la séparation des soucis entre mon View et ViewModel selon les buts et les principes de MVVM, j'ai placé cette logique supplémentaire dans mon code-behind pour garder la dépendance le code View. J'ai utilisé un hachage du contenu AddedItems de l'argument args pour distinguer les appels "repeat" en raison de la liaison de propriété sur un autre ComboBox à partir de nouveaux appels à la méthode de gestion d'événements en raison de l'interaction de l'utilisateur.

int hashCode = 0; 
    private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     string addedItemsCatString = ""; 
     foreach (string item in e.AddedItems) addedItemsCatString += item; 
     int newHashCode = addedItemsCatString.GetHashCode(); 
     if (newHashCode == hashCode) return; 
     hashCode = newHashCode; 

     // execute Command code here 
    } 

concaténant le contenu de AddedItems n'est pas strictement nécessaire pour une zone de liste déroulante où un seul élément peut être sélectionné à la fois, mais il permet une approche similaire sur les contrôles sélectionner plusieurs.

Méthode 2

Depuis que je suis pas complètement satisfait de la méthode 1, je pensais à une meilleure solution. L'idée qui m'est venue était que je ne cherchais vraiment à émettre la commande qu'une seule fois, basée sur une interaction de l'utilisateur. Ce qui ressemble à un bon drapeau pour distinguer un événement SelectionChanged dû à une interaction de l'utilisateur de ceux dus à une liaison de propriété est le focus du clavier.

private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    if (!(sender as FrameworkElement).IsKeyboardFocusWithin) return; 

     // execute Command code here 

} 

En tant que tel le test ci-dessus peut être la meilleure solution pour la majorité des cas, y compris ceux où un événement SelectionChanged est initié par un autre mode d'entrée ne comportant pas l'un de vos sélecteurs GUI, comme un raccourci clavier ou un changement interne de l'état de votre programme - ou n'importe quel endroit où vous pourriez exécuter une commande qui entraînerait le déclenchement de plusieurs événements SelectionChanged si vous utilisiez plusieurs contrôles pour contrôler un paramètre. La propriété d'instance FrameworkElement.IsKeyboardFocused et la méthode statique Keyboard.Focus (frameworkElementInstance) peuvent également être utiles pour différents contrôles ou scénarios.

Plus sur le focus du clavier peut être trouvé sur msdn here.

Questions connexes