2011-10-03 1 views
2

que je fais quelque chose comme ce qui suit pour empêcher une sélection d'onglet de changer:WPF Cancelling provoque la sélection Tab Changer l'événement de se produire deux fois

tabControl.Items.CurrentChanging += new CurrentChangingEventHandler(Items_CurrentChanging); 

void Items_CurrentChanging(object sender, CurrentChangingEventArgs e) 
{ 
    if(dataIsInvalid) 
    { 
      // Show some popup message 
      var item = ((ICollectionView)sender).CurrentItem; 
      e.Cancel = true; 
      tabControl.SelectedItem = item; // !! This causes the CurrentChanging event to happen twice !! 
              // But without this the visual tree does not update! :( 
    } 
} 

Cependant, le problème que je vois en ce moment est que la dernière ligne ci-dessus provoque un événement CurrentChanging à se produire une deuxième fois, et mon message contextuel est affiché deux fois. Non seulement cela, il est affiché la deuxième fois après avoir d'abord mis au point une autre fenêtre, puis de mettre l'accent sur la fenêtre de mon contrôle onglet. Des idées pour lesquelles cela pourrait se produire?

--EDIT-- Il semble que je devrais vraiment seulement besoin e.Cancel et ne nécessite pas de mettre à jour le SelectedItem nouveau. Cependant, l'arborescence visuelle n'est pas mise à jour sauf si je le fais. Est-il possible de s'assurer que l'arborescence visuelle du contrôle onglet est mis à jour après e.Cancel se produit, sans avoir à mettre à jour le SelectedItem?

+0

Est-ce que 'e.Cancel = true' fonctionne non seulement? – LPL

+0

Je suis d'accord avec LPL sur le e.Cancel. Personnellement, je n'aime pas les popups. Une autre approche consiste à valider l'entrée et à afficher l'erreur de validation via la validation. Et vous pouvez même désactiver tous les autres onglets sur une erreur de validation. – Paparazzi

+0

malheureusement juste en utilisant 'e.Cancel' ne fonctionne pas, la sélection de l'onglet change encore: s Il semble que cette personne a eu un problème similaire: http://stackoverflow.com/questions/4194290/is-there-a-way -to-cancel-tabcontrol-items-currentchanging mais la solution de contournement provoque un comportement étrange pour moi, comme je l'ai décrit ci-dessus. –

Répondre

2

Oui, c'est un peu bizarre ... vous pouvez décrocher de manière déterministe et accrocher le gestionnaire d'événements changeant en cours dans le contrôle onglet PreviewMouseDown. Dans CurrentChanging lui-même, décrochez le gestionnaire afin qu'il ne soit pas appelé plusieurs fois au moins.

private void MyTabControl_PreviewMouseDown(object sender, MouseButtonEventArgs e) 
    { 
     var tabControl = sender as TabControl; 

     if (tabControl != null) 
     { 
      var temp = new CurrentChangingEventHandler((sender1, e1) => { }); 
      var handler = new CurrentChangingEventHandler(
       (sender1, e1) => 
        { 
         var item = ((ICollectionView) sender1).CurrentItem; 
         if (item != null && dataIsInvalid) 
         { 
          e1.Cancel = true; 
          Dispatcher.BeginInvoke(
           new Action(() => 
            { 
             tabControl.SelectedItem = item; 
            })); 
         } 

         tabControl.Items.CurrentChanging -= temp; 
        }); 

      temp = handler; 
      tabControl.Items.CurrentChanging -= handler; 
      tabControl.Items.CurrentChanging += handler; 
     } 
    } 

J'espère que cela aide.

0

Cette question est ancienne mais j'ai juste rencontré ce problème maintenant avec un contrôle de tabulation. Tout ce que j'ai fait, c'est que j'ai désengagé le gestionnaire avant de l'appeler.

InsturmentTabs.Items.CurrentChanging -= new CurrentChangingEventHandler(Items_CurrentChanging); 
InsturmentTabs.Items.CurrentChanging += new CurrentChangingEventHandler(Items_CurrentChanging); 

private void Items_CurrentChanging(object sender, CurrentChangingEventArgs e) 
    { 
     if (condition) 
     { 
      var item = ((ICollectionView)sender).CurrentItem; 
      e.Cancel = true; 

      InsturmentTabs.SelectedItem = item;    
     }           
    }  
Questions connexes