Bir form yüklendikten SONRA kodu nasıl çalıştırırım?


126

.NET'te, Windows Forms'da Form yüklenmeden önce tetiklenen bir olay vardır (Form.Load), ancak form yüklendikten SONRA tetiklenen karşılık gelen olay yoktur. Form yüklendikten sonra biraz mantık yürütmek istiyorum.

Herhangi biri bir çözüm önerebilir mi?


Bu sorunun çok iyi cevapları olmasına rağmen, bundan bahsetmeye değer olabilir: docs.microsoft.com/en-us/dotnet/framework/winforms/…
Rishav

Yanıtlar:


192

"Gösterilen" olayını kullanabilirsiniz: MSDN - Form.Shown

"Gösterilen olay yalnızca bir form ilk kez görüntülendiğinde ortaya çıkar; daha sonra simge durumuna küçültmek, büyütmek, geri yüklemek, gizlemek, göstermek veya geçersiz kılmak ve yeniden boyamak bu olayı ortaya çıkarmayacaktır."


10
Bana, form yüklenirken gösterilen işleyici çalıştırılmış gibi görünüyor ... yanılıyor muyum?
ckonig

3
Eski ama altın ... Evet, yanılıyorsun. GUI paralel görevler yürütemez, başka bir yürütme yapılırken önemli olan bir şey yapmaktır.
Dennis Ziolkowski

2
Load olay işleyicisinde Application.DoEvents () öğesini çağıran bir kod varsa, Shown olayı, Load olay işleyicileri yürütmeyi bitirmeden önce tetiklenir. Bunun nedeni, Shown olayının aslında Form.BeginInvoke (ShownEvent) ve DoEvents () kullanılarak bir ileti kuyruğuna yerleştirilmesidir.
Artemix

1
Benim için C # da yeterli değildi. Başka bir başlıktaShown += Form1_Shown; önerildiği gibi eklemek zorunda kaldım
ocramot

11
This.Refresh () eklemelisiniz; Mantığınızdan önce gösterilen etkinliğin içinde ve mantığınız çalışmaya başlamadan önce formu tutup yenileyecek
Aylian Craspa

49

Bazen kullanıyorum (Yükte)

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

veya

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

(Olayı "this" dışında bir örnekte işliyorsanız "this" i form değişkeninize değiştirin).

Bu, çağrıyı windows-form döngüsüne iter, böylece form ileti kuyruğunu işlerken işlenir.

[istek üzerine güncellenir]

Control.Invoke / Control.BeginInvoke yöntemleri, iş parçacığı ile kullanılmak üzere tasarlanmıştır ve işi UI iş parçacığına itmek için bir mekanizmadır. Normalde bu işçi iş parçacıkları vb. Tarafından kullanılır. Control.Invoke zaman uyumlu bir çağrı yapar, burada Control.BeginInvoke zaman uyumsuz bir çağrı yapar.

Normalde bunlar şu şekilde kullanılır:

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

Bunu, Windows ileti kuyruğuna bir ileti göndererek yapar; UI iş parçacığı (bir noktada) mesajı sıradan çıkarır, temsilciyi işler ve işçiye tamamladığı sinyalini verir ... şimdiye kadar çok iyi ;-p

TAMAM; öyleyse UI iş parçacığında Control.Invoke / Control.BeginInvoke kullanırsak ne olur? Eğer Control.Invoke'u çağırırsanız, mesaj kuyruğundaki engellemenin anında bir kilitlenmeye neden olacağını bilmek yeterince mantıklıdır - bu nedenle, zaten UI iş parçacığındaysanız, kodu hemen çalıştırır ... böylece bize yardım etmiyor ...

Ancak Control.BeginInvoke farklı çalışır: zaten UI iş parçacığında olsak bile işi her zaman kuyruğa iter. Bu, "bir anda" demenin gerçekten basit bir yolunu yapar, ancak zamanlayıcıların vb. Rahatsızlığı olmadan (ki yine de aynı şeyi yapmak zorunda kalır!).


1
Bunu tam olarak anlamadım. Biraz daha açıklayabilir misin?
Torbjørn

Merhaba mark, BeginInvoke'da çağrılan işlem tamamlanırken formu duyarlı hale getirmek mümkün mü?
huMpty duMpty

WPF'de eşdeğeri nedir?
mrid

6

İlk kez "Yüklemeden Sonra" BAŞLAMAYACAKTIR
, sadece SONRAKİ Yüklemeyi başlatmak için kaydedecektir .

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.
}

5

Aynı sorunu yaşadım ve şu şekilde çözdüm:

Aslında Mesajı göstermek ve 2 saniye sonra otomatik olarak kapatmak istiyorum. Bunun için (dinamik olarak) basit bir form ve mesajı gösteren bir etiket oluşturmam gerekiyordu, mesajı 1500 ms boyunca durdurarak kullanıcının okuması gerekiyordu. Ve dinamik olarak oluşturulan formu kapatın. Gösterilen olay, yükleme olayından sonra gerçekleşir. Yani kod

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

2

Kodunuzu formun Etkinleştirilen olayına, formun tam olarak etkinleştirildiğinde gerçekleşmesini istiyorsanız da koymayı deneyebilirsiniz. Yalnızca ilk etkinleştirmede çalışması gerekiyorsa, bir boole "yürütüldü" denetimi koymanız gerekir.


1

Bu eski bir sorudur ve daha çok rutinlerinizi ne zaman başlatmanız gerektiğine bağlıdır. Hiç kimse bir boş referans istisnası istemediğinden, her zaman en iyisi önce null olup olmadığını kontrol etmek ve sonra gerektiğinde kullanmaktır; bu tek başına sizi çok fazla kederden kurtarabilir.

Bu türden bir sorunun en yaygın nedeni, bir kapsayıcı veya özel kontrol türünün, bu özelliklerin henüz başlatılmadığı özel bir sınıfın dışında başlatılan özelliklere erişmeye çalışması ve dolayısıyla potansiyel olarak boş değerlerin doldurulmasına ve hatta boş referans istisnalarına neden olabilmesidir. nesne türleri hakkında. Bu, sınıfınızın tam olarak başlatılmadan önce çalıştığı anlamına gelir - siz özelliklerinizi ayarlamayı bitirmeden önce vb. Bu türden bir sorunun olası bir diğer nedeni, özel grafiklerin ne zaman gerçekleştirileceğidir.

Form yükleme olayından sonra kodun ne zaman çalıştırılacağına ilişkin soruyu en iyi yanıtlamak, WM_Paint mesajını izlemek veya doğrudan boyama olayının kendisine bağlanmaktır. Neden? Boya olayı yalnızca form yükleme olayınıza göre tüm modüller tam olarak yüklendiğinde tetiklenir. Not: This.visible == true, true olarak ayarlandığında her zaman doğru değildir, bu nedenle bir formu gizlemek dışında bu amaç için hiç kullanılmaz.

Aşağıda, form load olayının ardından kodunuzu çalıştırmaya nasıl başlayacağınıza dair eksiksiz bir örnek verilmiştir. Boya mesaj döngüsünü gereksiz yere bağlamamanız önerilir, böylece kodunuzu bu döngünün dışında çalıştırmaya başlayacak bir olay oluşturacağız.

using System.Windows.Forms;

ad alanı 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

}

}


Bu inanılmaz derecede uzun soluklu görünüyor ve sadece Shown olayını yakalamaya göre herhangi bir avantajı var mı?
Steve Smith

0

Bunun eski bir yazı olduğunu biliyorum. Ama işte bunu nasıl yaptım:

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

    private void OpenFile(string myFile = null)
    {
            MessageBox.Show(myFile);
    }

-9

Bazı işlemlerden sonra formunuzu kapatabilirsiniz ..

//YourForm.ActiveForm.Close ();

    LoadingForm.ActiveForm.Close();
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.