ใน. NET Windows Forms มีเหตุการณ์ที่เริ่มทำงานก่อนที่ฟอร์มจะถูกโหลด (Form.Load) แต่ไม่มีเหตุการณ์ที่เกี่ยวข้องที่จะเริ่มทำงานหลังจากที่ฟอร์มโหลด ฉันต้องการเรียกใช้ตรรกะบางอย่างหลังจากโหลดแบบฟอร์มแล้ว
ใครช่วยแนะนำวิธีแก้ปัญหาได้ไหม
ใน. NET Windows Forms มีเหตุการณ์ที่เริ่มทำงานก่อนที่ฟอร์มจะถูกโหลด (Form.Load) แต่ไม่มีเหตุการณ์ที่เกี่ยวข้องที่จะเริ่มทำงานหลังจากที่ฟอร์มโหลด ฉันต้องการเรียกใช้ตรรกะบางอย่างหลังจากโหลดแบบฟอร์มแล้ว
ใครช่วยแนะนำวิธีแก้ปัญหาได้ไหม
คำตอบ:
คุณสามารถใช้เหตุการณ์ "Shown": MSDN - Form.Shown
"เหตุการณ์ที่แสดงจะถูกยกขึ้นในครั้งแรกที่มีการแสดงแบบฟอร์มเท่านั้นการย่อขนาดการขยายใหญ่การคืนค่าการซ่อนการแสดงหรือการทำให้ไม่ถูกต้องและการทาสีใหม่จะไม่ทำให้เหตุการณ์นี้เกิดขึ้น"
บางครั้งฉันใช้ (ในโหลด)
this.BeginInvoke((MethodInvoker) delegate {
// some code
});
หรือ
this.BeginInvoke((MethodInvoker) this.SomeMethod);
(เปลี่ยน "this" เป็นตัวแปรรูปแบบของคุณหากคุณจัดการเหตุการณ์บนอินสแตนซ์อื่นที่ไม่ใช่ "this")
สิ่งนี้จะผลักการเรียกไปยังลูปแบบฟอร์ม windows ดังนั้นจึงได้รับการประมวลผลเมื่อฟอร์มกำลังประมวลผลคิวข้อความ
[อัปเดตตามคำขอ]
เมธอด Control.Invoke / Control BeginInvoke มีไว้สำหรับใช้กับเธรดและเป็นกลไกในการพุชงานไปยังเธรด UI โดยปกติจะใช้โดยเธรดของผู้ปฏิบัติงานเป็นต้น ControlInvoke ทำการโทรแบบซิงโครนัสโดยที่ - เป็น ControlBeginInvoke ทำการโทรแบบอะซิงโครนัส
โดยปกติสิ่งเหล่านี้จะใช้เป็น:
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 เธรด UI (ในบางจุด) ยกเลิกการจัดคิวข้อความประมวลผลผู้รับมอบสิทธิ์และส่งสัญญาณให้ผู้ปฏิบัติงานทราบว่าเสร็จสิ้น ... จนถึงขณะนี้ดีมาก ;-p
ตกลง; แล้วจะเกิดอะไรขึ้นถ้าเราใช้ Control.Invoke / ControlBeginInvoke บนเธรด UI มัน copes ... ถ้าคุณเรียก ControlInvoke มันสมเหตุสมผลมากพอที่จะรู้ว่าการบล็อกคิวข้อความจะทำให้เกิดการชะงักงันทันทีดังนั้นหากคุณอยู่ในเธรด UI อยู่แล้วมันก็รันโค้ดทันที ... ไม่ช่วยเรา ...
แต่ ControlBeginInvoke ทำงานแตกต่างกัน: มันจะผลักดันงานไปยังคิวเสมอแม้ว่าเราจะอยู่ในเธรด UI แล้วก็ตาม นี่เป็นวิธีง่ายๆในการพูดว่า "อีกสักครู่" แต่หากไม่มีตัวจับเวลาที่ไม่สะดวก ฯลฯ (ซึ่งก็ยังคงต้องทำแบบเดิมอยู่ดี!)
ครั้งแรกจะไม่เริ่ม "AfterLoading"
เพียงแค่ลงทะเบียนเพื่อเริ่มการโหลดครั้งต่อไป
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.
}
ฉันมีปัญหาเดียวกันและแก้ไขได้ดังนี้:
อันที่จริงฉันต้องการแสดงข้อความและปิดโดยอัตโนมัติหลังจากผ่านไป 2 วินาที สำหรับสิ่งนั้นฉันต้องสร้างรูปแบบง่ายๆ (แบบไดนามิก) และหนึ่งป้ายกำกับที่แสดงข้อความหยุดข้อความเป็นเวลา 1,500 มิลลิวินาทีเพื่อให้ผู้ใช้อ่าน และปิดแบบฟอร์มที่สร้างขึ้นแบบไดนามิก เหตุการณ์ที่แสดงเกิดขึ้นหลังจากเหตุการณ์โหลด ดังนั้นรหัสคือ
Form MessageForm = new Form();
MessageForm.Shown += (s, e1) => {
Thread t = new Thread(() => Thread.Sleep(1500));
t.Start();
t.Join();
MessageForm.Close();
};
คุณยังสามารถลองใส่รหัสของคุณในเหตุการณ์ที่เปิดใช้งานของแบบฟอร์มหากคุณต้องการให้เกิดขึ้นเมื่อเปิดใช้งานแบบฟอร์ม คุณจะต้องใส่บูลีน "ได้ดำเนินการ" ตรวจสอบว่าควรจะรันเมื่อเปิดใช้งานครั้งแรกเท่านั้น
คำถามนี้เป็นคำถามเก่าและขึ้นอยู่กับว่าคุณต้องเริ่มกิจวัตรเมื่อใด เนื่องจากไม่มีใครต้องการข้อยกเว้นการอ้างอิงที่เป็นโมฆะจึงควรตรวจสอบค่าว่างก่อนจากนั้นจึงใช้ตามความจำเป็น เพียงอย่างเดียวอาจช่วยให้คุณหายเศร้าได้มาก
สาเหตุที่พบบ่อยที่สุดสำหรับคำถามประเภทนี้คือเมื่อคอนเทนเนอร์หรือชนิดการควบคุมแบบกำหนดเองพยายามเข้าถึงคุณสมบัติที่กำหนดค่าเริ่มต้นภายนอกคลาสที่กำหนดเองซึ่งคุณสมบัติเหล่านั้นยังไม่ได้รับการเตรียมใช้งานซึ่งอาจทำให้เกิดค่า null เพื่อเติมข้อมูลและอาจทำให้เกิดข้อยกเว้นการอ้างอิงว่าง ในประเภทวัตถุ หมายความว่าชั้นเรียนของคุณกำลังทำงานก่อนที่จะเริ่มต้นอย่างสมบูรณ์ - ก่อนที่คุณจะตั้งค่าคุณสมบัติของคุณเสร็จเป็นต้นอีกเหตุผลที่เป็นไปได้สำหรับคำถามประเภทนี้คือเมื่อใดที่จะต้องแสดงกราฟิกแบบกำหนดเอง
เพื่อให้ตอบคำถามได้ดีที่สุดเกี่ยวกับเวลาที่จะเริ่มเรียกใช้โค้ดหลังจากเหตุการณ์โหลดแบบฟอร์มคือการมอนิเตอร์ข้อความ WM_Paint หรือเชื่อมโยงโดยตรงกับเหตุการณ์การระบายสี ทำไม? เหตุการณ์สีจะเริ่มทำงานก็ต่อเมื่อโมดูลทั้งหมดโหลดเต็มตามเหตุการณ์การโหลดแบบฟอร์มของคุณ หมายเหตุ: This.visible == 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
}
}
ฉันรู้ว่านี่เป็นโพสต์เก่า แต่นี่คือวิธีที่ฉันได้ทำ:
public Form1(string myFile)
{
InitializeComponent();
this.Show();
if (myFile != null)
{
OpenFile(myFile);
}
}
private void OpenFile(string myFile = null)
{
MessageBox.Show(myFile);
}
คุณสามารถปิดแบบฟอร์มของคุณได้หลังจากดำเนินการเสร็จสิ้น ..
//YourForm.ActiveForm.Close ();
LoadingForm.ActiveForm.Close();