153 votes

Comment exécuter un code APRÈS le chargement d'un formulaire ?

Dans .NET, les formulaires Windows ont un événement qui se déclenche avant le chargement du formulaire (Form.Load), mais il n'y a pas d'événement correspondant qui se déclenche APRÈS le chargement du formulaire. Je voudrais exécuter une certaine logique après le chargement du formulaire.

Quelqu'un peut-il me conseiller une solution ?

1 votes

Bien que cette question ait de très bonnes réponses, il serait bon de mentionner ceci : docs.microsoft.com/fr/us/dotnet/framework/winforms/

223voto

Matthias Schippling Points 881

Vous pourriez utiliser l'événement "Shown" : MSDN - Form.Shown

"L'événement Shown n'est soulevé que la première fois qu'un formulaire est affiché ; par la suite, la réduction, l'agrandissement, le rétablissement, le masquage, l'affichage ou l'invalidation et le repeint ne soulèveront pas cet événement."

15 votes

Il me semble que le gestionnaire affiché est exécuté PENDANT que le formulaire se charge... Ai-je tort ?

5 votes

Vieux mais en or... Oui, vous avez tort. L'interface graphique ne peut pas exécuter des tâches parallèles, ce qui est important c'est de faire quelque chose pendant qu'une autre exécution est en cours.

2 votes

Si dans le gestionnaire d'événement Load il y a un code qui appelle Application.DoEvents(), l'événement Shown se déclenche avant que les gestionnaires d'événement Load aient terminé leur exécution. Cela est dû au fait que l'événement Shown est en fait placé dans une file d'attente de messages à l'aide de Form.BeginInvoke(ShownEvent) et que DoEvents() le force à se déclencher avant la fin de Load.

53voto

Marc Gravell Points 482669

J'utilise parfois (en charge)

this.BeginInvoke((MethodInvoker) delegate {
  // some code
});

ou

this.BeginInvoke((MethodInvoker) this.SomeMethod);

(remplacez "this" par votre variable de formulaire si vous traitez l'événement sur une instance autre que "this").

Cela place l'invocation dans la boucle Windows-forms, de sorte qu'elle est traitée lorsque le formulaire traite la file d'attente des messages.

[mis à jour sur demande]

Les méthodes Control.Invoke/Control.BeginInvoke sont destinées à être utilisées avec le threading et constituent un mécanisme permettant de pousser le travail sur le thread de l'interface utilisateur. Normalement, cette méthode est utilisée par les threads de travail, etc. Control.Invoke effectue un appel synchrone, alors que Control.BeginInvoke effectue un appel asynchrone.

Normalement, ils sont utilisés comme :

SomeCodeOrEventHandlerOnAWorkerThread()
{
  // this code running on a worker thread...
  string newText = ExpensiveMethod(); // perhaps a DB/web call

  // now ask the UI thread to update itself
  this.Invoke((MethodInvoker) delegate {
      // this code runs on the UI thread!
      this.Text = newText;
  });
}

Il le fait en poussant un message dans la file d'attente des messages de Windows ; le thread de l'interface utilisateur (à un moment donné) retire le message de la file d'attente, traite le délégué, et signale au travailleur qu'il a terminé... jusqu'ici tout va bien ;-p

OK ; alors que se passe-t-il si nous utilisons Control.Invoke / Control.BeginInvoke sur le thread UI ? Il s'en sort... si vous appelez Control.Invoke, il est suffisamment intelligent pour savoir que le blocage sur la file d'attente des messages provoquerait un blocage immédiat - donc si vous êtes déjà sur le thread UI, il exécute simplement le code immédiatement... donc cela ne nous aide pas...

Mais Control.BeginInvoke fonctionne différemment : il toujours pousse le travail dans la file d'attente, même si nous sommes déjà sur le fil de l'interface utilisateur. C'est une façon très simple de dire "dans un moment", mais sans l'inconvénient des minuteries, etc (qui devraient toujours faire la même chose de toute façon !)

1 votes

Je n'ai pas tout à fait compris celui-là. Pouvez-vous expliquer un peu plus ?

0 votes

Bonjour Mark, est-il possible de rendre le formulaire réactif pendant la fin du processus appelé dans BeginInvoke ?

0 votes

Quel est son équivalent dans WPF ?

10voto

Ahmed Sabry Points 377

La première fois, il ne démarre pas "AfterLoading",
Il va juste l'enregistrer pour démarrer la prochaine charge.

private void Main_Load(object sender, System.EventArgs e)
{
    //Register it to Start in Load 
    //Starting from the Next time.
    this.Activated += AfterLoading;
}

private void AfterLoading(object sender, EventArgs e)
{
    this.Activated -= AfterLoading;
    //Write your code here.
}

5voto

Sharmila Points 11

J'ai eu le même problème, et je l'ai résolu comme suit :

En fait, je veux afficher le message et le fermer automatiquement après 2 secondes. Pour cela, j'ai dû générer (dynamiquement) un formulaire simple et une étiquette montrant le message, arrêter le message pendant 1500 ms pour que l'utilisateur le lise. Et fermer le formulaire créé dynamiquement. L'événement affiché se produit après l'événement de chargement. Le code est donc

Form MessageForm = new Form();
MessageForm.Shown += (s, e1) => { 
    Thread t = new Thread(() => Thread.Sleep(1500)); 
    t.Start(); 
    t.Join(); 
    MessageForm.Close(); 
};

3voto

Mitchel Sellers Points 38352

Vous pouvez également essayer de placer votre code dans l'événement Activated du formulaire, si vous voulez qu'il se produise uniquement lorsque le formulaire est activé. Il vous faudra cependant ajouter une vérification booléenne "a exécuté" si le code n'est censé s'exécuter qu'à la première activation.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X