ในทางจิตวิทยาแล้วผู้พัฒนาโปรแกรมควรให้ความสำคัญในส่วนนี้มากพอสมควรเลยทีเดียว จริงๆแล้วในวงการนักพัฒนา Software มีข้อห้ามที่รู้ๆกันดีว่าในสิ่งที่ไม่ควรให้ User ได้เห็นคือ
- ห้ามมี Error Message แบบที่ไม่คาดคิด ข้อนี้รุนแรงที่สุด เพราะผู้พัฒนาอาจจะไม่สามารถอธิบายได้
- ถ้าการทำงานได้ผลผิดพลาด ก็ควรจะมีเหตุผลที่ดี พูดให้ User ฟังได้ลื่นหู (แก้ตัวให้ขึ้นนั่นแหละ)
- ไม่ควรให้ User รอการทำงานของโปรแกรมนาน โดยที่โปรแกรมของเราดูแปลกๆ ไม่รู้ว่ามันทำงานอยู่หรือ Hang ไปแล้ว ซึ่งวิธีแก้ไม่ยาก ต้องมีอะไรขยับ หรือมีสถานะให้ User เห็น
การทำ Waiting Dialog รูปแบบนึงในการแก้ปัญหา และทำให้ User มีความสบายใจ และทำให้โปรแกรมที่เราพัฒนาขึ้นดูเป็นมืออาชีพ
สำหรับมือใหม่ ผู้เขียนจะสาธิตการสร้าง Waiting Dialog ง่ายๆ เพื่อความเข้าใจและนำไปประยุคใช้ได้ เริ่มแรกก็คือการสร้าง Project Windows Application ขึ้นมา โดย Project นี้ผู้เขียนจะใช้ฟอร์มเพียง 2 ฟอร์ม คือ ฟอร์มหลัก ชื่อ frmMain และ และฟอร์มที่จะใช้เป็น Waiting Dialog ชื่อ DlgWait
frmMain ในมุมมองออกแบบประกอบด้วย
Panel > panel1 : ใช้เป็น Container ของปุ่ม
Button > RUN : ปุ่มกดเพื่อเริ่มทำงาน
Button > Cancel : ปุ่มกดเพื่อหยุดทำงาน
Panel > panel2 : ใช้เป็น Container ของ DataGridView
frmMain |
DlgWait ในมุมมองออกแบบประกอบด้วย
Label > label1 : ข้อความ "รอสักครู่..."
progressBar > progressBar1 : ใช้สำหรับแสดงสถานะการทำงาน
DlgWait |
ในส่วนของ DlgWait ผู้เขียนไม่ได้ใส่ Code การทำงานใดๆ แต่กำหนดค่าลงไปใน Constructor เท่านั้น
public partial class DlgWait : Form
{
public DlgWait()
{
InitializeComponent();
//กำหนดรูปแบบของฟอร์มเป็นแบบ none
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
//กำหนดให้คุณสมบัติของฟอร์มเป็น topmost ในตอนแสดงจะอยู่เหนือทุกอย่าง
this.TopMost = true;
//รูปแบบของ progressBar ให้เป็นแบบ Marquee (วิ่งไปมา)
this.progressBar1.Style = ProgressBarStyle.Marquee;
}
}
คราวนี้มาถึงการทำงานที่อยู่ใน frmMain ผู้เขียนจะให้มีการทำงานคือ สุ่มชื่อเพื่อนๆขึ้นมาแสดงบน DataGridView โดยที่จะทำการสุ่มอายุด้วย โดยอายุที่จะเป็นเพื่อนได้น่าจะ - หรือ + 10 ปี
ภาพรวมของ Class frmMain |
อธิบาย Code ทั้งหมด
//ส่วนของ Member
private DataGridView dgv;
private BindingSource BS;
private DataSet DS;
private DataTable TB;
private Random random;
//กำหนดค่าคงที่เป็นอายุไว้
private const int myAge = 30;
//ค่าของการยกเลิกเป็น false
private bool cancel=false;
ภายใน Constructor จะเป็นการสร้างทรัพยากรทั้งหมดที่ต้องใช้ คือ การสร้าง DataSet และ DataTable ที่มี Column พร้อมใช้งาน การสร้าง DataGrideView เพื่อแสดงข้อมูล
public frmMain()
{
InitializeComponent();
//สร้าง Object ในการสุ่มค่า
this.random = new Random();
//สร้าง DataTable ชื่อ WAITDATA
this.TB = new DataTable("WAITDATA");
//สร้าง Column ให้ DataTable 3 Column คือ ID , FRIEND_NAME และ FRIEND_AGE
this.TB.Columns.Add(new DataColumn("ID", System.Type.GetType("System.Int32")));
this.TB.Columns.Add(new DataColumn("FRIEND_NAME",System.Type.GetType("System.String")));
this.TB.Columns.Add(new DataColumn("FRIEND_AGE", System.Type.GetType("System.Int32")));
//สร้าง Dataset เพื่อเก็บ DataTable
this.DS=new DataSet();
this.DS.Tables.Add(this.TB);
//สร้าง BindingSource ส่งผ่านข้อมูลกับ DataSet
this.BS = new BindingSource(this.DS, "WAITDATA");
//สร้าง DataGridView ให้อยู่ใน panel 2 ที่ออกแบบไว้แล้ว พร้อมระบุให้ใช้ข้อมูลผ่าน BindingSource ชื่อ BS
this.dgv = new DataGridView();
this.dgv.Dock = DockStyle.Fill;
this.dgv.Parent = this.panel2;
this.dgv.MultiSelect = false;
this.dgv.ReadOnly = true;
this.dgv.DataSource = this.BS;
}
method ต่อมาที่สร้างคือ getRandonFriend เป็น method ที่จะคือค่าจากการสุ่ม พร้อมกัน 2 ค่า คือ ชื่อ และอายุ โดยใช้ Parameter แบบ Pass by reference
private void getRandonFriend(ref string friendName,ref int friendAge)
{
string[] friend = {"เอกศักดิ์","สมชาย","วิชัย","ศศิชา","กัญญาลักษณ์","ชูวิทย์","สุพจน์","รวีวรรณ","ธีรพล" };
//สุ่มชื่อเพื่อน และอายุ ส่งไปที่ reference variable
friendName = friend[this.random.Next(friend.Length)];
friendAge = this.random.Next(myAge-10, myAge + 10);
}
สุดท้ายคือ method ซึ่งก็คือ Event ปุ่ม Run และ Cancel
private void RUN_Click(object sender, EventArgs e)
{
this.cancel = false;
this.RUN.Enabled = false;
//สร้าง Waiting Dialog ขึ้นมา
DlgWait w = new DlgWait();
//สั่งให้โชว์
w.Show(this);
try
{
//วนลูปเพื่อสุ่มรายชื่อเข้าใส่ตาราง
for (int i = 0; i < 100000; i++)
{
//หากสถานะ cancel เป็น true หมายความว่าให้หยุดการทำงานทันที
if (this.cancel) break;
Application.DoEvents();
//ประกาศตัวแปรเพื่อไปรับค่า
string friendNameValue = null;
int friendAgeValue = 0;
//สุ่มข้อมูลด้วย method getRandonFriend
this.getRandonFriend(ref friendNameValue, ref friendAgeValue);
// นำค่าสุ่มที่ได้มาเพิ่มเป็นข้อมูลใหม่ใน DataTable
DataRow dr = this.TB.NewRow();
dr["ID"] = i + 1;
dr["FRIEND_NAME"] = friendNameValue;
dr["FRIEND_AGE"] = friendAgeValue;
this.TB.Rows.Add(dr);
เมื่อลูปทำงานไป Waiting Dialog ก็จะ Update ตัวเองไปด้วย
w.Update();
}
}
finally
{
//เมื่อทำงานเสร็จสิ้น Waiting Dialog ก็หมดความหมาย ต้องทำลายทิ้ง
w.Close();
w.Dispose();
this.RUN.Enabled = true;
}
}
private void Cancel_Click(object sender, EventArgs e)
{
//ให้สถานะของ cancel เป็น true การทำงานจะได้หยุด
this.cancel = true;
this.RUN.Enabled = true;
}
เมื่อทดสอบโดยกดปุ่ม Run โปรแกรมก็จะทำงาน พร้อมกับแสดง Waiting Dialog ให้ User เห็น |
ชอบครับอิอิ
ตอบลบ