Bagaimana cara saya mengeksekusi kode SETELAH formulir dimuat?

126

Di .NET, Formulir Windows memiliki peristiwa yang dijalankan sebelum Formulir dimuat (Form.Load), tetapi tidak ada peristiwa terkait yang diaktifkan SETELAH formulir dimuat. Saya ingin menjalankan beberapa logika setelah formulir dimuat.

Adakah yang bisa memberi nasihat tentang solusi?

adeel825
sumber
Meskipun pertanyaan ini memiliki jawaban yang sangat bagus, mungkin ada baiknya menyebutkan ini: docs.microsoft.com/en-us/dotnet/framework/winforms/…
Rishav

Jawaban:

192

Anda dapat menggunakan acara "Shown": MSDN - Form.Shown

"Acara yang Ditampilkan hanya dimunculkan saat pertama kali formulir ditampilkan; kemudian meminimalkan, memaksimalkan, memulihkan, menyembunyikan, menampilkan, atau membatalkan dan mengecat ulang tidak akan meningkatkan acara ini."

Matthias Schippling
sumber
10
Bagi saya sepertinya penangan yang ditampilkan dijalankan SAAT formulir sedang dimuat ... apakah saya salah?
ckonig
3
Tua tapi emas ... Ya, Anda salah. GUI tidak dapat menjalankan tugas paralel, yang penting untuk melakukan sesuatu SAAT eksekusi lain dilakukan.
Dennis Ziolkowski
2
Jika dalam Load event handler ada kode yang memanggil Application.DoEvents (), event Shown dijalankan sebelum penanganan event Load menyelesaikan eksekusinya. Ini karena acara yang ditampilkan sebenarnya diletakkan dalam antrean pesan menggunakan Form.BeginInvoke (ShownEvent) dan DoEvents () memaksanya untuk diaktifkan sebelum Muat selesai.
Artemix
1
Itu tidak cukup tidak berhasil bagi saya, di C #. Saya harus menambahkan Shown += Form1_Shown;seperti yang disarankan di utas lain
ocramot
11
Anda harus menambahkan This.Refresh (); di dalam acara Tampil terlebih dahulu sebelum logika Anda dan itu akan menahan dan menyegarkan formulir untuk dimuat sepenuhnya sebelum logika Anda mulai berjalan
Aylian Craspa
49

Saya terkadang menggunakan (di Load)

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

atau

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

(ubah "ini" ke variabel formulir Anda jika Anda menangani peristiwa pada instance selain "ini").

Ini mendorong pemanggilan ke loop bentuk jendela, sehingga diproses saat formulir memproses antrian pesan.

[diperbarui berdasarkan permintaan]

Metode Control.Invoke / Control.BeginInvoke dimaksudkan untuk digunakan dengan threading, dan merupakan mekanisme untuk mendorong pekerjaan ke thread UI. Biasanya ini digunakan oleh utas pekerja dll. Control.Invoke melakukan panggilan sinkron, di mana-karena Control.BeginInvoke melakukan panggilan asinkron.

Biasanya, ini akan digunakan sebagai:

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

Ini dilakukan dengan mendorong pesan ke antrian pesan windows; UI thread (di beberapa titik) membatalkan antrian pesan, memproses delegasi, dan memberi sinyal kepada pekerja bahwa itu telah diselesaikan ... sejauh ini sangat bagus ;-p

BAIK; jadi apa yang terjadi jika kita menggunakan Control.Invoke / Control.BeginInvoke pada UI thread? Ini mengatasi ... jika Anda memanggil Control.Invoke, cukup masuk akal untuk mengetahui bahwa pemblokiran pada antrian pesan akan menyebabkan kebuntuan langsung - jadi jika Anda sudah berada di thread UI, kode akan langsung menjalankannya ... tidak membantu kami ...

Tetapi Control.BeginInvoke bekerja secara berbeda: ia selalu mendorong pekerjaan ke antrian, meskipun kita sudah berada di thread UI. Ini membuat cara yang sangat sederhana untuk mengatakan "dalam sekejap", tetapi tanpa ketidaknyamanan pengatur waktu dll (yang tetap harus melakukan hal yang sama!).

Marc Gravell
sumber
1
Tidak sepenuhnya mengerti yang satu itu. Bisakah Anda menjelaskan lebih banyak?
Torbjørn
Hai tandai, apakah mungkin membuat formulir menjadi responsif saat proses selesai yang disebut di BeginInvoke ??
huMpty duMpty
apa yang setara di WPF?
mrid
6

Pertama kali TIDAK AKAN memulai "AfterLoading",
Ini hanya akan mendaftarkannya untuk memulai NEXT Load.

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

Saya memiliki masalah yang sama, dan menyelesaikannya sebagai berikut:

Sebenarnya saya ingin menampilkan Pesan dan menutupnya secara otomatis setelah 2 detik. Untuk itu saya harus menghasilkan form sederhana (dinamis) dan satu label yang menampilkan pesan, stop message selama 1500 ms sehingga user membacanya. Dan Tutup formulir yang dibuat secara dinamis. Acara yang ditampilkan terjadi setelah acara pemuatan. Jadi kodenya

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

Anda juga dapat mencoba meletakkan kode Anda di acara Activated dari formulir, jika Anda ingin itu terjadi, tepat ketika formulir diaktifkan. Anda harus memasukkan cek boolean "telah dieksekusi" meskipun jika itu hanya harus dijalankan pada aktivasi pertama.

Penjual Mitchel
sumber
1

Ini pertanyaan lama dan lebih bergantung pada kapan Anda perlu memulai rutinitas Anda. Karena tidak ada yang menginginkan pengecualian referensi null, yang terbaik adalah memeriksa null terlebih dahulu, lalu gunakan sesuai kebutuhan; Itu saja bisa menyelamatkan Anda dari banyak kesedihan.

Alasan paling umum untuk jenis pertanyaan ini adalah ketika wadah atau jenis kontrol kustom mencoba mengakses properti yang diinisialisasi di luar kelas kustom di mana properti tersebut belum diinisialisasi sehingga berpotensi menyebabkan nilai null terisi dan bahkan dapat menyebabkan pengecualian referensi null pada tipe objek. Ini berarti kelas Anda berjalan sebelum sepenuhnya diinisialisasi - sebelum Anda selesai menyetel properti Anda, dll. Alasan lain yang mungkin untuk jenis pertanyaan ini adalah kapan harus melakukan grafik kustom.

Untuk menjawab pertanyaan terbaik tentang kapan harus mulai menjalankan kode setelah peristiwa pemuatan formulir adalah dengan memantau pesan WM_Paint atau mengait langsung ke peristiwa cat itu sendiri. Mengapa? Peristiwa paint hanya diaktifkan ketika semua modul telah dimuat sepenuhnya sehubungan dengan peristiwa pemuatan formulir Anda. Catatan: This.visible == true tidak selalu benar jika diset true sehingga tidak digunakan sama sekali untuk tujuan ini kecuali untuk menyembunyikan formulir.

Berikut ini adalah contoh lengkap tentang cara mulai menjalankan kode Anda setelah peristiwa pemuatan formulir. Disarankan agar Anda tidak mengikat loop pesan paint secara tidak perlu sehingga kami akan membuat acara yang akan mulai mengeksekusi kode Anda di luar loop tersebut.

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

}

}

Jamie
sumber
Ini tampaknya sangat bertele-tele, dan apakah itu memiliki keuntungan lebih dari sekadar menyaksikan acara Tampil?
Steve Smith
0

Saya tahu ini adalah posting lama. Tapi inilah cara saya melakukannya:

    public Form1(string myFile)
    {
        InitializeComponent();
        this.Show();
        if (myFile != null)
        {
            OpenFile(myFile);
        }
    }

    private void OpenFile(string myFile = null)
    {
            MessageBox.Show(myFile);
    }
J. Fischlein
sumber
-9

Anda dapat menutup formulir Anda setelah beberapa eksekusi ..

//YourForm.ActiveForm.Close ();

    LoadingForm.ActiveForm.Close();
E Coder
sumber