Як виконати код ПІСЛЯ завантаження форми?


126

У .NET, у формах Windows є подія, яка запускається перед завантаженням форми (Form.Load), але немає відповідної події, яка запускається ПІСЛЯ завантаження форми. Я хотів би виконати певну логіку після завантаження форми.

Хтось може порадити рішення?


Хоча на це питання є дуже хороші відповіді, можливо, варто згадати про це: docs.microsoft.com/en-us/dotnet/framework/winforms/…
Rishav

Відповіді:


192

Ви можете використовувати подію "Показано": MSDN - Form.Shown

"Показувана подія піднімається лише при першому відображенні форми; згодом мінімізація, максимізація, відновлення, приховування, показ або вимкнення та перефарбування не призведе до цієї події."


10
Мені здається, що показаний обробник виконаний, коли форма завантажується ... я помиляюся?
ckonig

3
Старий, але золото ... Так, ви помиляєтесь. Графічний інтерфейс не може виконувати паралельні завдання, що важливо зробити що-небудь при виконанні іншого виконання.
Dennis Ziolkowski

2
Якщо в обробнику подій Load є код, який викликає Application.DoEvents (), Подія показується, перш ніж обробники подій Load закінчили виконання. Це тому, що Подія, що відображається, насправді ставиться в чергу повідомлень за допомогою Form.BeginInvoke (ShownEvent), а DoEvents () змушує її запускати до завершення завантаження.
Артемікс

1
Це було недостатньо для мене роботи, в C #. Мені довелося додати, Shown += Form1_Shown;як пропонується в іншій темі
окламот

11
слід додати This.Refresh (); всередині Показуваного події спочатку перед вашою логікою, і він буде тримати та оновлювати форму до повного завантаження до початку логіки
Айліан Краспа

49

Я іноді використовую (в Load)

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

або

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

(змінити "це" на змінну вашої форми, якщо ви обробляєте подію в екземплярі, відмінному від "цього").

Це натискає на виклик циклу вікон-форм, тому він обробляється, коли форма обробляє чергу повідомлень.

[оновлено на запит]

Методи Control.Invoke / Control.BeginInvoke призначені для використання з нарізкою різьби та є механізмом для поштовху роботи на потоці інтерфейсу користувача. Зазвичай для цього використовують робочі потоки тощо. Control.Invoke робить синхронний дзвінок, де-як Control.BeginInvoke робить асинхронний виклик.

Зазвичай вони використовуються як:

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

Це робиться шляхом натискання повідомлення на чергу повідомлень Windows; потік користувальницького інтерфейсу (в якийсь момент) виводить з черги повідомлення, обробляє делегата та сигналізує працівникові, що воно завершено ... поки що добре ;-p

ГАРАЗД; так що станеться, якщо ми використовуємо Control.Invoke / Control.BeginInvoke на потоці інтерфейсу? Він справляється ... якщо ви зателефонуєте Control.Invoke, досить розумно знати, що блокування в черзі повідомлень призведе до негайного тупику - тому, якщо ви вже в потоці інтерфейсу, він просто запустить код негайно ... так що не допомагає нам ...

Але Control.BeginInvoke працює по-іншому: він завжди висуває роботу на чергу, навіть якщо ми вже є в потоці інтерфейсу. Це робить насправді простим способом сказати "за мить", але без незручностей таймерів тощо (що все одно доведеться робити те саме!).


1
Не зрозумів повністю того. Чи можете ви пояснити трохи більше?
Torbjørn

Привіт, позначте, чи можна зробити форму чуйною, поки процес завершено, який називається в BeginInvoke ??
huMpty duMpty

що таке еквівалент у WPF?
середина

6

Перший раз НЕ БУДЕ запускати "AfterLoading",
він просто зареєструє його, щоб запустити 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.
}

5

У мене була така ж проблема, і я вирішив її так:

Насправді я хочу показати Повідомлення і автоматично закрити його через 2 секунди. Для цього мені довелося генерувати (динамічно) просту форму та одну мітку, що показує повідомлення, стоп-повідомлення на 1500 мс, щоб користувач прочитав його. І Закрийте динамічно створену форму. Показано подію після події завантаження. Так що код є

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

2

Ви також можете спробувати ввести свій код у події активованої форми, якщо ви хочете, щоб він стався саме тоді, коли форма активована. Вам потрібно буде поставити булеву перевірку "виконав", хоча якщо вона повинна працювати лише при першій активації.


1

Це старе питання і більше залежить від того, коли вам потрібно розпочати свої процедури. Оскільки ніхто не хоче винятку з нульовим посиланням, завжди краще спершу перевірити нуль, а потім використовувати за потребою; це одне може врятувати вам багато горя.

Найбільш частою причиною такого типу питань є те, коли контейнер або користувальницький тип управління намагається отримати доступ до властивостей, ініціалізованих поза спеціальним класом, де ці властивості ще не були ініціалізовані, таким чином потенційно можуть викликати нульові значення для заповнення і навіть можуть спричинити нульові посилання виключення на типи об'єктів Це означає, що ваш клас працює до того, як він буде повністю ініціалізований - до того, як ви закінчите налаштування властивостей тощо. Ще одна можлива причина такого типу питань - коли виконувати власну графіку.

Найкраще відповісти на питання про те, коли розпочати виконання коду після події завантаження форми - це відстежувати повідомлення WM_Paint або підключити безпосередньо до самої події фарби. Чому? Подія фарби запускається лише тоді, коли всі модулі повністю завантажені стосовно події завантаження форми. Примітка. Ця невидима == true не завжди відповідає дійсності, коли вона встановлена ​​істиною, тому вона взагалі не використовується для цієї мети, крім приховування форми.

Нижче наведено повний приклад того, як почати виконання коду після події завантаження форми. Рекомендується не надмірно зв’язувати цикл повідомлень фарби, тому ми створимо подію, яка почне виконувати ваш код поза цим циклом.

using System.Windows.Forms;

простір імен 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

}

}


Це здається неймовірно довголюбивим, і чи є у нього якісь переваги перед просто ловом на показ шоу?
Стів Сміт

0

Я знаю, що це стара публікація. Але ось як я це зробив:

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

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

-9

Ви можете закрити форму після деякого виконання ..

//YourForm.ActiveForm.Close ();

    LoadingForm.ActiveForm.Close();
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.