it-swarm.com.de

Wie führe ich Code aus, nachdem ein Formular geladen wurde?

In .NET hat Windows Forms ein Ereignis, das ausgelöst wird, bevor das Formular geladen wird (Form.Load), aber es gibt kein entsprechendes Ereignis, das ausgelöst wird, nachdem das Formular geladen wurde. Ich möchte eine Logik ausführen, nachdem das Formular geladen wurde.

Kann mir jemand eine Lösung empfehlen?

117
adeel825

Sie können das Ereignis "Shown" verwenden: MSDN - Form.Shown

"Das angezeigte Ereignis wird nur ausgelöst, wenn ein Formular zum ersten Mal angezeigt wird. Wenn Sie es anschließend minimieren, maximieren, wiederherstellen, ausblenden, anzeigen oder ungültig machen und neu zeichnen, wird dieses Ereignis nicht ausgelöst."

175

Ich benutze manchmal (in Load)

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

oder

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

(Ändern Sie "this" in Ihre Formularvariable, wenn Sie das Ereignis in einer anderen Instanz als "this" behandeln.).

Dadurch wird der Aufruf in die Windows-Forms-Schleife verschoben, sodass er verarbeitet wird, wenn das Formular die Nachrichtenwarteschlange verarbeitet.

[auf Anfrage aktualisiert]

Die Control.Invoke/Control.BeginInvoke-Methoden sind für die Verwendung mit Threading vorgesehen und stellen einen Mechanismus zum Pushen von Arbeit auf den UI-Thread dar. Normalerweise wird dies von Worker-Threads usw. verwendet. Control.Invoke führt einen synchronen Aufruf aus, wohingegen Control.BeginInvoke einen asynchronen Aufruf ausführt.

Normalerweise werden diese verwendet als:

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;
  });
}

Dazu wird eine Nachricht in die Windows-Nachrichtenwarteschlange verschoben. Der UI-Thread stellt die Nachricht (an einem bestimmten Punkt) aus der Warteschlange, verarbeitet den Delegaten und signalisiert dem Worker, dass sie abgeschlossen wurde

OKAY; Was passiert also, wenn wir Control.Invoke/Control.BeginInvoke im UI-Thread verwenden? Wenn Sie Control.Invoke aufrufen, ist es sinnvoll zu wissen, dass das Blockieren der Nachrichtenwarteschlange zu einem sofortigen Deadlock führen würde. Wenn Sie sich also bereits im UI-Thread befinden, wird der Code einfach sofort ausgeführt hilft uns nicht ...

Control.BeginInvoke funktioniert jedoch anders: Es immer verschiebt die Arbeit in die Warteschlange, auch wenn wir uns bereits im UI-Thread befinden. Dies ist eine wirklich einfache Art, "in einem Moment" zu sagen, aber ohne die Unannehmlichkeiten von Timern usw. (die sowieso immer noch dasselbe tun müssten!).

45
Marc Gravell

Beim ersten Mal wird "AfterLoading" NICHT gestartet.
Es wird nur registriert, um NEXT Load zu starten.

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.
}
6
Ahmed Sabry

Ich hatte das gleiche Problem und löste es wie folgt:

Eigentlich möchte ich Message anzeigen und nach 2 Sekunden automatisch schließen. Dafür musste ich eine (dynamisch) einfache Form und ein Etikett mit der Meldung erzeugen, die Meldung für 1500 ms anhalten, damit der Benutzer sie las. Und dynamisch erstelltes Formular schließen. Gezeigtes Ereignis tritt nach dem Ladeereignis auf. Code ist also

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

Sie können auch versuchen, Ihren Code in das Activated-Ereignis des Formulars einzufügen, wenn Sie möchten, dass er nur dann auftritt, wenn das Formular aktiviert wird. Sie müssten jedoch eine boolesche Prüfung "hat ausgeführt" eingeben, wenn sie nur bei der ersten Aktivierung ausgeführt werden soll.

2
Mitchel Sellers

Dies ist eine alte Frage und hängt mehr davon ab, wann Sie Ihre Routinen starten müssen. Da niemand eine Nullreferenzausnahme haben möchte, ist es immer am besten, zuerst nach Null zu suchen und diese dann nach Bedarf zu verwenden. das allein kann dir viel Kummer ersparen.

Der häufigste Grund für diese Art von Frage ist der Versuch eines Containers oder eines benutzerdefinierten Steuerelementtyps, auf Eigenschaften zuzugreifen, die außerhalb einer benutzerdefinierten Klasse initialisiert wurden, wobei diese Eigenschaften noch nicht initialisiert wurden. Dies kann möglicherweise dazu führen, dass Nullwerte ausgefüllt werden und sogar Nullreferenzausnahmen auftreten auf Objekttypen. Dies bedeutet, dass Ihre Klasse ausgeführt wird, bevor sie vollständig initialisiert wurde - bevor Sie Ihre Eigenschaften usw. festgelegt haben. Ein weiterer möglicher Grund für diese Art von Frage ist, wann benutzerdefinierte Grafiken ausgeführt werden sollen.

Um die Frage zu beantworten, wann die Ausführung von Code nach dem Formularladeereignis beginnen soll, müssen Sie die WM_Paint-Nachricht überwachen oder sich direkt an das Paint-Ereignis anschließen. Warum? Das Paint-Ereignis wird nur ausgelöst, wenn alle Module in Bezug auf Ihr Formularladeereignis vollständig geladen wurden. Hinweis: This.visible == true ist nicht immer true, wenn es auf true gesetzt ist. Daher wird es zu diesem Zweck nur zum Ausblenden eines Formulars verwendet.

Im Folgenden finden Sie ein vollständiges Beispiel für den Beginn der Codeausführung nach dem Formularladeereignis. Es wird empfohlen, die Paint-Meldungsschleife nicht unnötig zu verknüpfen, damit ein Ereignis erstellt wird, bei dem der Code außerhalb dieser Schleife ausgeführt wird.

using System.Windows.Forms;

namespace MyProgramStartingPlaceExample {

/// <summary>
/// Main UI form object
/// </summary>
public class Form1 : Form
{

    /// <summary>
    /// Main form load event handler
    /// </summary>
    public Form1()
    {
        // Initialize ONLY. Setup your controls and form parameters here. Custom controls should wait for "FormReady" before starting up too.
        this.Text = "My Program title before form loaded";
        // Size need to see text. lol
        this.Width = 420;

        // Setup the sub or fucntion that will handle your "start up" routine
        this.StartUpEvent += StartUPRoutine;

        // Optional: Custom control simulation startup sequence:
        // Define your class or control in variable. ie. var MyControlClass new CustomControl;
        // Setup your parameters only. ie. CustomControl.size = new size(420, 966); Do not validate during initialization wait until "FormReady" is set to avoid possible null values etc. 
        // Inside your control or class have a property and assign it as bool FormReady - do not validate anything until it is true and you'll be good! 
    }

    /// <summary>
    /// The main entry point for the application which sets security permissions when set.
    /// </summary>
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }


    #region "WM_Paint event hooking with StartUpEvent"            
    //
    // Create a delegate for our "StartUpEvent"
    public delegate void StartUpHandler();
    //
    // Create our event handle "StartUpEvent"
    public event StartUpHandler StartUpEvent;
    //
    // Our FormReady will only be set once just he way we intendded
    // Since it is a global variable we can poll it else where as well to determine if we should begin code execution !!
    bool FormReady;
    //
    // The WM_Paint message handler: Used mostly to Paint Nice things to controls and screen
    protected override void OnPaint(PaintEventArgs e)
    {
        // Check if Form is ready for our code ?
        if (FormReady == false) // Place a break point here to see the initialized version of the title on the form window
        {
            // We only want this to occur once for our purpose here.
            FormReady = true;
            //
            // Fire the start up event which then will call our "StartUPRoutine" below.
            StartUpEvent();
        }
        //
        // Always call base methods unless overriding the entire fucntion
        base.OnPaint(e);
    }
    #endregion


    #region "Your StartUp event Entry point"
    //
    // Begin executuing your code here to validate properties etc. and to run your program. Enjoy!
    // Entry point is just following the very first WM_Paint message - an ideal starting place following form load
    void StartUPRoutine()
    {
        // Replace the initialized text with the following
        this.Text = "Your Code has executed after the form's load event";
        //
        // Anyway this is the momment when the form is fully loaded and ready to go - you can also use these methods for your classes to synchronize excecution using easy modifications yet here is a good starting point. 
        // Option: Set FormReady to your controls manulaly ie. CustomControl.FormReady = true; or subscribe to the StartUpEvent event inside your class and use that as your entry point for validating and unleashing its code.
        //
        // Many options: The rest is up to you!
    }
    #endregion

}

}

1
Jamie