2010-03-17 2 views
4

HaiWPF chargement de contrôle de l'utilisateur deux fois

ai un contrôle utilisateur WPF, quand j'utilise ce contrôle dans une autre fenêtre de le charger à deux reprises, de sorte que son exception de lancer pour moi, coz vais avoir une fonction dans l'événement usercontrol_loaded, lorsqu'elle En chargeant deux fois l'erreur de lancement, y at-il un autre moyen de vérifier si le contrôle userc est chargé comme ça, sinon comment résoudre ce problème.

Répondre

7

Longue histoire courte, utilisez un drapeau booléen:

private bool firstLoad = true; 
    private void UserControl_Loaded(object sender, RoutedEventArgs e) 
    { 
     if (firstLoad) 
     { 
      firstLoad = false; 

      // Do somthing that want to do only once... 
     } 
    } 

plus longue histoire: Apparemment, dans WPF vous ne pouvez pas supposer l'événement chargé est tiré qu'une seule fois.

J'ai rencontré la même situation en utilisant un contrôle utilisateur dans un Tabitem. Chaque fois que vous activez un Tabitem en le sélectionnant, l'événement chargé est déclenché pour tous les contrôles de ce tableau.

Salutations

0

Oui, je trouve ce comportement vraiment bizarre. En fin de compte, je pense que ce que Hertzel a dit est la meilleure façon de faire - ou de dériver une nouvelle classe UserControl comme ceci:

Vous pouvez dériver des éléments de LoadOnceUserControl et son événement FirstLoaded ne sera appelé qu'une seule fois.

using System.Windows; 
using System.Windows.Controls; 
public class LoadOnceUserControl : UserControl 
{ 
    private bool firstLoadCalled = false; 

    public LoadOnceUserControl() 
    { 
     // Hook up our loaded event 
     this.Loaded += new RoutedEvent(delegate(object sender, RoutedEventArgs e) 
     { 
      // If FirstLoad hasn't been called and there are events to be called... 
      if (!this.firstLoadCalled && this.FirstLoaded != null) 
      { 
       this.FirstLoaded(sender, e); 
      } 

      // We've already called (or attempted to call) FirstLoad. 
      this.firstLoadCalled = true; 
     }); 
    } 

    event RoutedEventHandler FirstLoaded; 
} 
+0

zane - c'est très gentil de votre part que vous vouliez partager tout le monde avec cette utilité, mais la prochaine fois que vous sentirez cette envie, s'il vous plaît faites-en un peu hm .. robuste. ce code semble simple, mais il a plusieurs défauts de conception qui ne peuvent que coûter plus aux utilisateurs, ne donnant rien à leur tour. Au moins deux choses sont perceptibles à première vue, et je veux vraiment dire premier coup d'œil, pas d'analyse plus profonde! La première est que vous n'invoquez pas l'événement en toute sécurité/correctement. Deuxièmement, il n'y a AUCUN intérêt à ce qu'un tel gestionnaire anonyme soit encore attaché après la détection de la deuxième invocation. – quetzalcoatl

5

Après avoir écrit un commentaire au poste de Zane, une après pensée est venue à moi: en fait, vous ne voulez pas utiliser cette solution avec le drapeau booléen, ou vous devez le rendre encore plus robuste.

Il est admis qu'un contrôle peut être RÉUTILISÉ. Cela signifie que le contrôle peut être ajouté à l'arborescence, puis supprimé, ajouté, supprimé et ainsi de suite. Si vous avez vraiment besoin de filtrer les invocations multiples de Loaded, vous devez également suivre l'événement Unloaded!

Suivant l'exemple de Zane, il devrait ressembler à code suivant:

using System.Windows; 
using System.Windows.Controls; 
public class LoadOnceUserControl : UserControl 
{ 
    private bool firstLoadCalled = false; 

    public LoadOnceUserControl() 
    { 
     this.Unloaded += (sender,e) => firstLoadCalled = false; 

     this.Loaded += (sender,e) => 
     { 
      if (this.firstLoadCalled) return; 
      this.firstLoadCalled = true; 

      var copy = this.FirstLoaded; 
      if (copy != null) copy(sender,e); 
     }); 
    } 

    /*public*/ event RoutedEventHandler FirstLoaded; 
} 

S'il vous plaît noter qu'il pourrait être raisonnable aussi ajouter FirstUnloaded analogue juste pour la symétrie. Je ne l'ai jamais vu appeler faussement bien. Et l'esprit que, malgré waht je l'ai écrit dans le commentaire à Zane - dans cette approche, vous ne doit pas détacher que les gestionnaires

7

Vous ne pas besoin d'un « firstLoadCalled » drapeau si vous le faites de cette façon:

public MyControl() 
{ 
    this.Loaded += MyControl_Loaded; 
} 

private void MyControl_Loaded(object sender, RoutedEventArgs e) 
{ 
    this.Loaded -= MyControl_Loaded; //make it so MyControl_Loaded is only called once 

    /* code that runs once on first load */ 
} 
Questions connexes