C# WinApp Scope งานประมาณนี้ คิดราคา เท่าไหร่ครับ
สำหรับ ผมราคาอยู่ที่การออกแบบ database อันนี้เป็นประสบการณ์ อยู่ที่ความยากง่าย ของระบบ
อย่างของคุณนี้ ถ้าไม่มีระบบ staff manager แค่มี user login ธรรมดา ระบบ database ซัก 2หมื่น
ส่วนหน้าเพจ+หลังบ้าน กันเอง หน้าละ 6000 ถ้าเป็นคนอื่น 4000 (ราคาโดยประมาณ)
ทำไมกันเอง 6000 เพราะกันเองมันเรื่องมากกว่าคนอื่นอีก ระยะเวลาดูแลมันนานและเรื่องเยอะกว่าคนอื่น
และทำไมไม่เหมา เพราะถ้าเพิ่มหน้าเราเพิ่มเงิน ราคาชัดเจน ไม่ใช่อยากเพิ่มหน้าช่วยเพิ่มให้หน่อยนะแบบฟรี 5555
สัญญามักเป็นสัญญาใจ ทำกันตลอดชีวิต 5555 จนกว่าจะเลิกคบ แล้วมักจะเลิกคบกัน หลังงานจบซักปี 5555
แบบ กูเบื่อแล้ว แนะนำเขียนสัญญาด้วยนะครับ ให้ชัดเจนเหมือนคนอื่นจ้าง จะได้ไม่เสียเพื่อน มีประสบการณ์มาแล้ว
เป็นราคาสำหรับคนธรรมดาคิดซะว่าเป็นค่าล่วงเวลา
ส่วนราคา บริษัท ต้องบวกเพิ่มหลายอย่าง
ปล. แนะนำว่าอย่าทำที่บริษัท เพราะเราเป็นพนักงานบริษัท
เอาเวลาเขามาทำ มันจะโดนเพ่งเล่งได้ง่าย ส่วนคนธรรมดาก็ต้องดูความเหมาะสมด้วย
อย่างกรณีของคุณนี่ จริงๆ แค่ให้เขาไปเลี้ยงข้าวก็พอ เพราะเขารู้จักคุณและคนในบริษัทคุณ
ไม่เป็นผลดีกับหน้าที่การงานเท่าไหร่หรอกครับ เชื่อผม
Date :
2019-07-12 09:23:44
By :
Chaidhanan
ตอบความคิดเห็นที่ : 1 เขียนโดย : Chaidhanan เมื่อวันที่ 2019-07-12 09:23:44
รายละเอียดของการตอบ ::
โห........................... นี่ราคาจริงใช่ไม๊ครับ ทำไมแพงจัง 5555
ผมนี่ไปไม่ถูกเลย
แต่เขาเคยขอใบเสนอราคาจาก บ.ที่รับเขียนโปรแกรม แค่ในงานแล็บอย่างเดียว แสนกว่า ครับ
แล้วนี้ถ้าผมคิดตังที่เขียนให้บริษัทผมเอง ผมจะได้ได้เป็น 4-5 แสน เลยหรือครับ
เพราะมีเพิ่มทั้ง บันทึกประจำวัน งานจัดซื้อ งานออกใบเสนอราคา งานจัดการเครื่องมือ
คือทุกอย่างที่เกี่ยวกับแล็บผมลงในโปรแกรมหมดเลย
ส่วนเรื่องงานไม่เป็นไรครับ
ปกติ ผมจะเคลียงานเสร็จแล้วค่อยเขียน เพราะต้องเขียนให้ บริษัทด้วยครับ
ข้อดีของระบบคือ ลด ขั้นตอนการคำนวนลง เยอะมากครับ
จากแต่ก่อนต้องคำนวณเครื่องคิดเลข เป็นวัน ส่งหัวหน้าเช็คอีกวัน แล้วก็ส่งฝ่ายเพื่อรับรอง
ทุกวันนี้ user คำนวน หัวหน้ารับทราบ แค่ไม่กี่นาที เองครับ
ตอนนี้เขียนระบบใหม่ เพื่อรองรับ ISO 17025 ให้มากขึ้น มีระบบการเข้าถึงข้อมูลตามหน่วยงาน
และระบบสำรองข้อมูลที่ดีขึ้น และ พยายามเขียนให้กว้างขึ้น เพราะผมกะว่าจะเขียนแจกให้แล็บใช้ครับ
อย่างน้อยในแล็บก็จะมีบันทึก เครื่องชั่ง อุณหภูมิ ความชื้น การสั่งซื้อของ บันทึก เครื่องมือ การใช้ การสอบเทียบ การรักษา
การทำ PT การบันทึก control ต่างๆ ที่หลักๆ แต่ละแล็บต้องมีอยู่แล้ว
Date :
2019-07-12 09:53:31
By :
lamaka.tor
ถามนอกเรื่องครับ พอดีติด แล้วยังหาวิธีแก้ไม่ได้ครับ
Code (C#)
public static void SetGridDefaultCellStyle(this System.Windows.Forms.DataGridView dgv,int rowByKey = -1)
{
dgv.CellEnter += new DataGridViewCellEventHandler((object sender, DataGridViewCellEventArgs e) =>
{
// if (dgv[0, e.RowIndex].Value.GetType() == typeof(int))
rowByKey = e.RowIndex;
});
dgv.CellContentClick += new DataGridViewCellEventHandler((object sender, DataGridViewCellEventArgs e) =>
{
// if (dgv[0, e.RowIndex].Value.GetType() == typeof(int))
rowByKey = e.RowIndex;
});
}
โค้ดนี้ผมใช้เป็น Exten
ตอนใช้
Code (C#)
int rowIndex = -1;
public frmRec_HM_708()
{
InitializeComponent();
aLS_FH_708DataGridView.SetGridDefaultCellStyle(true, "", 7, 1, rowIndex);
}
คือผมอยากส่งค่า rowByKey ไปให้ rowIndex แต่ทำไมได้ซักที
ปัญหาคือ มันจำค่า rowByKey ตั้งแต่ตอน แรกไว้
เพราะผมลงไว้ใน public frmRec_HM_708()
ถ้าแก้จุดนี้ได้ โค้ด ในแต่ละฟอร์มจะลดลงอีกหลายฟอร์ม ครับ
ประวัติการแก้ไข 2019-07-12 11:12:11
Date :
2019-07-12 11:03:51
By :
lamaka.tor
4-5 แสน ทั้งระบบ ก็สมควรอยู่นะครับ
ส่วนคำถาม งงครับ
คือผมอยากส่งค่า rowByKey ไปให้ rowIndex แต่ทำไมได้ซักที
แล้วทำไม โค๊ดถีงได้เป็น rowByKey = e.rowIndex; ล่ะครับ
หรือ ต้องการ เซทค่า rowByKey ให้เท่ากับ e.rowIndex
และพอ มา function ล่างสุด rowIndex มาจากไหน
Date :
2019-07-12 14:37:36
By :
Chaidhanan
ตอบความคิดเห็นที่ : 6 เขียนโดย : Chaidhanan เมื่อวันที่ 2019-07-12 14:37:36
รายละเอียดของการตอบ ::
ทำได้แล้วครับ
พอดีผมเขียน extension method สำหรับ datagrid ไว้ครับ จะได้ไม่ต้องเขียนโค้ดในทุกฟอร์ม
เป็นการ ส่งค่า RowIndex ให้กับ ตัวแปรที่ประกาศไว้ในแต่ละ ฟอร์ม ครับ
โค้ดเต็มจะเป็นแบบนี้ครับ
Code (C#)
public static void SetGridDefaultCellStyle(this System.Windows.Forms.DataGridView dgv, bool canEdit = true, string AutoID = "", int clMan = -1, int clDate = -1, int rowByKey = -1, int colChehk_1 = -1, int colChehk_2= -1)
{
dgv.SetDefaultCellStyle();
if (!canEdit)
{
dgv.Columns[0].ReadOnly = true;
dgv.AllowUserToAddRows = false;
dgv.AllowUserToDeleteRows = false;
dgv.ReadOnly = true;
}
dgv.CellValueChanged += new DataGridViewCellEventHandler((object sender, DataGridViewCellEventArgs e) =>
{
DataGridView _dgv = sender as DataGridView;
if (e.RowIndex < 0) return;
if (!string.IsNullOrEmpty(UserLogin.EmployeeName))
dgv[(clMan == -1)?_dgv.ColumnCount - 2:clMan, e.RowIndex].Value = UserLogin.EmployeeName;
dgv[(clDate ==-1)?_dgv.ColumnCount - 1:clDate, e.RowIndex].Value = DateTime.Now;
if (!string.IsNullOrEmpty(AutoID) && string.IsNullOrEmpty(dgv[0, e.RowIndex].Value.ToString()))
{
dgv[0, e.RowIndex].Value = dgv.ToDataTable().AutoID(0, AutoID);
}
});
dgv.KeyDown += new KeyEventHandler((object sender, System.Windows.Forms.KeyEventArgs e) =>
{
if (e.KeyCode == System.Windows.Forms.Keys.Delete &&
System.Windows.Forms.MessageBox.Show("คุณต้องการลบข้อมูลหรือไม่", "Warning", System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.No
&& UserLogin.CheckUserConferm() == false)
{
DataGridView g = sender as DataGridView;
g.AllowUserToDeleteRows = false;
}
if (e.KeyCode == Keys.F12 && rowByKey >= 0 && colChehk_1 >=0 && colChehk_2 >= 0)
{
DataGridView g = sender as DataGridView;
for (int i = colChehk_1; i <= colChehk_2; i++)
dgv[i, rowByKey].Value = true;
}
});
dgv.CellEnter += new DataGridViewCellEventHandler((object sender, DataGridViewCellEventArgs e) =>
{
// if (dgv[0, e.RowIndex].Value.GetType() == typeof(int))
rowByKey = e.RowIndex;
});
}
จากตัวอย่าง 2 ฟอร์ม คือ ผมส่งค่า RowIndex ไปให้ SetGridDefaultCellStyle ในตัวปแปร rowByKey
แล้วเวลาเกิด CellEnter ให้
rowByKey = e.RowIndex;
หรือ ให้
RowIndex = e.RowIndex;
นั่นเองครับ
Date :
2019-07-12 16:09:19
By :
lamaka.tor
ไหนๆ ก้ ไหน ๆ อยากไขข้อข้องใจ หรือหาทางแก้ตรงจุดนี้ครับ
เหมือนมันเลี่ยงไปใช้โค้ดอื่น แล้วมันก็ยังไม่ แจบใจ(5555)
คำถามคือ จะสร้าง ฟังค์ชัน ที่มี Delegate และ ใน Delegate ให้ ส่งค่า _e.RowIndex ไปให้ rowIndex
คือ เรื่องของเรื่อง คือ ผมจะใช้ ค่า _e.RowIndex นั่นเองครับ
ถ้าแบบนี้ เราควรจะเขียน โค้ดยังไง ครับ เพื่อให้ _e.RowIndex ไปให้ rowIndex ได้
ต่อให้ผมเลี่ยงไปใช้อย่างอื่น แต่พอหวนกลับมา โค้ดเดิม มันก็ยังหาวิธีแก้ไม่ได้ซักที เลยอยากแก้ให้มัน แจบใจ ครับ
Date :
2019-07-12 17:29:21
By :
lamaka.tor
แหมไม่ยากจะติเลยนะ เอามาเป็นภาพ เหมือน guest เพิ่งลงทะเบียนเลย
ผมว่าระหว่างก๊อปเทค กับก๊อบภาพนี่ ก็อปเทคมันง่ายกว่านะ
การผ่านตัวแปรแบบ pointer จะสามารถส่งค่ากับไปยัง class ที่เรียกใช้มันได้
Code (C#)
void Foo( ref string s, ref int x )
{
s = "Hello World"; // caller sees the change to s
x = 100; // caller sees the change to x
}
ประวัติการแก้ไข 2019-07-13 05:37:08 2019-07-13 06:03:17 2019-07-13 06:04:13
Date :
2019-07-13 05:36:13
By :
Chaidhanan
ต้องขอโทษด้วยครับ
Code (C#)
public partial class Form1 : Form
{
int rowIndex = -1;
public Form1()
{
InitializeComponent();
}
void SetGrid(DataGridView gd, int row)
{
dataGridView1.CellEnter += new DataGridViewCellEventHandler((object _sender, DataGridViewCellEventArgs _e) =>
{
MessageBox.Show("dgv.CellEnter += new DataGridViewCellEventHandler" + _e.RowIndex);
row = _e.RowIndex;
});
}
private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.F12)
MessageBox.Show(" private void dataGridView1_KeyDown" + rowIndex);
}
private void Form1_Load(object sender, EventArgs e)
{
SetGrid(dataGridView1, rowIndex);
}
}
ถ้าส่งค่าจาก ฟังค์ชัน มันส่งได้ครับ
แต่พอ มี Delegate มามันส่งไม่ได้
Date :
2019-07-13 08:13:45
By :
lamaka.tor
ได้ลองตามตัวอย่างที่ผมให้ไปหรือยังครับ
Date :
2019-07-13 09:34:31
By :
Chaidhanan
Code (C#)
void SetGrid(DataGridView gd, int row) // ตัวแปร row ไม่ได้ถูกประกาศเป็น reference (pointer)
{
// บันทัดข้างล่างนี้ เป็น การกำหนด function ให้กับ event ที่ยังไม่ได้ทำงานจริง
// ต้องถือว่ามัน เป็นอีก function ที่อยู่นอก SetGrid ไม่ได้อยู่ภายใน ตรงนี้ เข้าใจหรือเปล่าบอกมาด้วยจะได้อธิบายเพิ่ม
gd.CellEnter += new DataGridViewCellEventHandler((object _sender, DataGridViewCellEventArgs _e) =>
{
MessageBox.Show("dgv.CellEnter += new DataGridViewCellEventHandler" + _e.RowIndex);
row = _e.RowIndex;
// ตัวแปร row ตรงนี้ ถูก compile กับตัวแปรที่ไม่ได้เป็น reference
// --> เน้นนะครับ compile กับตัวแปรที่ไม่ได้เป็น reference
// ก็จะอยู่แค่ ภายใน SetGrid เท่านั้น ไม่ได้ออกไปยัง function ที่เรียกมัน
// คำสั่งนี้ SetGrid(dataGridView1, rowIndex); rowIndex จะไม่ถูกเปลี่ยน
});
}
// ถ้าเขียนแบบข้างล่างนี้ เพิ่ม ref หน้าตัวแปร int row
void SetGrid(DataGridView gd, ref int row) // ตัวแปร row ่ได้ถูกประกาศเป็น reference (pointer)
{
gd.CellEnter += new DataGridViewCellEventHandler((object _sender, DataGridViewCellEventArgs _e) =>
{
MessageBox.Show("dgv.CellEnter += new DataGridViewCellEventHandler" + _e.RowIndex);
row = _e.RowIndex;
// ตัวแปร row ตรงนี้ ก็จะถูก compile กับตัวแปรที่เป็น reference
// ก็จะส่งผ่านออกไปยัง function ที่เรียกใช้มันได้
// คำสั่งนี้ SetGrid(dataGridView1, rowIndex); rowIndex จะถูกเปลี่ยน
});
}
ประวัติการแก้ไข 2019-07-13 12:50:51
Date :
2019-07-13 12:46:48
By :
Chaidhanan
Code (C#)
static int rowIndex;
void setGrid(DataGridView gd, ref int row)
{
dataGridView1.CellEnter += (sender, e) => ASS(sender, e);
dataGridView1.KeyDown += new KeyEventHandler(DataGridView1_KeyDown);
}
static void ASS(object sender, DataGridViewCellEventArgs e)
{
rowIndex = e.RowIndex;
}
private void DataGridView1_KeyDown (object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.F12)
{
MessageBox.Show("ass ass: " + rowIndex);
}
}
Date :
2019-07-13 13:49:34
By :
xxx
ถ้าดูจากคำสั่งนี้และถ้าเดาไม่ผิดคุณต้องการดัก CurrentRow/CurrentCell ของกริดตัวที่คุณต้องการ (ตัวเดียว/หลายตัว)
Code (C#)
SetGrid(dataGridView1, rowIndex); rowIndex จะถูกเปลี่ยน
ถ้าลองเปลี่ยนเป็นแบบนี้ละ
Code (C#)
SetGrid(dataGridView1, dataGridView1.Tag); rowIndex จะถูกเปลี่ยน
Code (C#)
// ถ้าเขียนแบบข้างล่างนี้ เพิ่ม ref หน้าตัวแปร int row
void SetGrid(DataGridView gd, string row) // ตัวแปร row ่ได้ถูกประกาศเป็น reference (pointer)
{
gd.CellEnter += new DataGridViewCellEventHandler((object _sender, DataGridViewCellEventArgs _e) =>
{
MessageBox.Show("dgv.CellEnter += new DataGridViewCellEventHandler" + _e.RowIndex);
gd.Tag = _e.RowIndex;
// ตัวแปร row ตรงนี้ ก็จะถูก compile กับตัวแปรที่เป็น reference
// ก็จะส่งผ่านออกไปยัง function ที่เรียกใช้มันได้
// คำสั่งนี้ SetGrid(dataGridView1, dataGridView1.Tag); rowIndex จะถูกเปลี่ยน
});
gd.KeyDown += new KeyEventHandler(gd_KeyDown);
}
private void gd_KeyDown (object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.F12)
{
MessageBox.Show("ass : " + ((DataGridView)sender).Tag);
}
}
Date :
2019-07-13 16:40:40
By :
xxx
ลองทำเป็น ตัวอย่าง form เท่านั้น ขีเกียจสร้าง datagrid ต่อ มันเยอะวุ่นวาย
Code (C#)
namespace WindowsFormsApp1
{
class Class1
{
public long _tag { get; set; }
public Form2 _frm { get; set; }
}
}
Code (C#)
using System;
using System.Collections.Generic;
//using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
//using System.Drawing;
//using System.Linq;
//using System.Text;
//using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form2 : Form
{
public Form1 pForm;
public Form2()
{
InitializeComponent();
}
public void setDefaultMethod(Form1 x, string tb_name, EventHandler btEventClick)
{
pForm = x;
string[] flds = getColumnsName(tb_name);
string slcFlds = String.Join(", ", flds);
string stmt = stmt1Page(tb_name, slcFlds, "", "id", 0, 50);
Dgv1.DataSource = GetTable(tb_name, stmt);
SetHeaderGrid(flds);
button1.Click += btEventClick; // method for event Button_Click
}
public string[] getColumnsName(string tb_name)
{
List<string> listacolumnas = new List<string>();
using (SqlCommand command = pForm.cnn.CreateCommand())
{
command.CommandText = "SELECT top 1 t.* FROM (select 0 id) as a left join "+tb_name+" as t on a.id=t.id";
using (var reader = command.ExecuteReader(CommandBehavior.KeyInfo))
{
reader.Read();
var table = reader.GetSchemaTable();
foreach (DataRow row in table.Rows)
{
listacolumnas.Add(row.ItemArray[0].ToString());
}
}
}
return listacolumnas.ToArray();
}
public string stmt1Page(string tb_name, string slcFlds, string _Where, string fld_id, int _CurPage, int _PageSize)
{
int _intSkip = _CurPage * _PageSize;
string _strSql = string.Concat(new object[]
{
"SELECT TOP ", _PageSize,
" * FROM (SELECT ", slcFlds, " FROM ", tb_name , " ", _Where, ") as tb1 ",
"WHERE ", fld_id, " NOT IN (SELECT TOP ", _intSkip, " ",fld_id," FROM ", tb_name, " ", _Where,")"
});
return _strSql;
}
public DataTable GetTable(string tb_name, string stmt)
{
DataTable _dt = new DataTable();
SqlCommand _cmd = pForm.cnn.CreateCommand();
_cmd.CommandText = stmt;
SqlDataAdapter _da = new SqlDataAdapter(_cmd);
DataSet _ds = new DataSet();
_da.Fill(_ds, tb_name);
_dt = _ds.Tables[tb_name];
return _dt;
}
private void SetHeaderGrid(string[] flds)
{
int i = 0;
while (i < flds.Length)
{
Dgv1.Columns[i].HeaderText = flds[i]; i++;
}
}
private void Form2_FormClosed(object sender, FormClosedEventArgs e)
{
long x = (long)Tag;
pForm.F2Close( x );
int _t = (int)pForm.timer1.Tag;
if ( _t <1 )
{
pForm.timer1.Tag = 1; pForm.timer1.Start();
}
Dispose();
}
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
Dgv1.Tag = e.RowIndex;
}
private void Dgv1_CellEnter(object sender, DataGridViewCellEventArgs e)
{
Dgv1.Tag = e.RowIndex;
//MessageBox.Show("Enter = " + e.RowIndex);
}
private void Dgv1_CellLeave(object sender, DataGridViewCellEventArgs e)
{
//MessageBox.Show("Out = " + Dgv1.Tag);
}
}
}
Code (C#)
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
private List<Class1> Frms;
private List<long> CloseList;
public SqlConnection cnn;
public string cnxString;
public Timer timer1;
public string tb_name;
public Form1()
{
InitializeComponent();
cnxString = @"Data Source=192.168.1.15;Initial Catalog=MyDB;User Id=adminweb;Password=xxxxx;";
cnn = new SqlConnection(cnxString);
cnn.Open();
}
private void Form1_Load(object sender, EventArgs e)
{
Frms = new List<Class1>();
CloseList = new List<long>();
timer1 = new Timer();
timer1.Tick += timer1_Tick;
timer1.Tag = 0;
timer1.Interval = 500;
timer1.Enabled = false;
cbTableList.SelectedIndex = 0;
}
public void F2Close(long x)
{
CloseList.Add(x);
}
private void btSave0(object _sender, EventArgs _e)
{
MessageBox.Show("Test btSave 0 : " + ((Button)_sender).Text);
}
private void btSave1(object _sender, EventArgs _e)
{
MessageBox.Show("Test btSave 1 : "+((Button)_sender).Text);
}
private void button1_Click(object sender, EventArgs e)
{
Class1 x = new Class1();
DateTime y = new DateTime();
x._frm = new Form2();
x._tag = y.Ticks;
x._frm.Tag = x._tag;
switch (cbTableList.SelectedIndex)
{
case 0: x._frm.setDefaultMethod(this, tb_name, btSave0); break;
case 1: x._frm.setDefaultMethod(this, tb_name, btSave1); break;
default:
//
break;
}
x._frm.Show();
Frms.Add(x);
textBox1.Text = Frms.Count.ToString();
}
private void timer1_Tick(object sender, EventArgs e)
{
do {
long x = CloseList[0];
int c = Frms.Count;
int i = 0;
do
{
if (Frms[i]._tag == x)
{
//Frms[i]._frm.Dispose();
Frms.Remove(Frms[i]); i = c;
CloseList.Remove(CloseList[0]);
break;
}
i++;
} while (i < c);
} while (CloseList.Count>0);
timer1.Stop();
timer1.Tag = 0;
textBox1.Text = Frms.Count.ToString();
}
private void cbTableList_SelectedIndexChanged(object sender, EventArgs e)
{
tb_name = cbTableList.Items[cbTableList.SelectedIndex].ToString();
}
}
}
ประวัติการแก้ไข 2019-07-13 21:40:44 2019-07-13 21:43:51 2019-07-14 21:49:57 2019-07-14 21:51:11
Date :
2019-07-13 21:34:03
By :
Chaidhanan
คือคำว่าคล้ายกัน มันก็คือคนละ form ยังไงก็ต้องสร้างแยกกัน
แต่เราสามารถสร้าง templete ที่เหมือนกันมากที่สุด
แล้ว inherit มาสร้าง form ที่แตกต่างแต่ละอย่างออกไป
Date :
2019-07-14 08:00:53
By :
Chaidhanan
ตอบความคิดเห็นที่ : 23 เขียนโดย : lamaka.tor เมื่อวันที่ 2019-07-13 22:24:18
รายละเอียดของการตอบ ::
ถ้าเป็นผม จะทำเป็น base form
ไม่จำเป็นต้องสร้าง 10-20 ฟอร์ม ให้รกโปรเจ็ค ใช้งานก็แค่โยนสิ่งที่ต้องการเข้าไปเท่านั้น
base form แค่ทำการบอกแบบในงานที่ต้องการทำซ้ำๆเหมือนๆกัน เช่น save update delete
การทำงานจริงมันอยู่ที่ ที่ class โน้น
และอีกอย่างนะ Syteline ระบบที่บริษัทใช้งานอยุ่เขาก้ไม่ได้ใช้งานฟอร์มเดียวแล้วเทพทุกอย่างหรอกนะ
เอาจริงๆ โปรแกรมเมอร์ส่วนใหญ่มั้ง(อาจจะเป็นผมคนเดียวก็ได้) เขาไม่มาเสียเวลาเรืองพวกนี้หรอก
ที่จะมาสร้างอะไรให้วุ่นวาย เขาต้องการงานที่ง่ายรวดเร็ว คนอืนทำต่อได้ เห็นโค้ดเขาใจง่ายแก้ไขได้ ไม่ผูกกับ
object มากเกินไป น้อยหนักที่จะ BindingSource ลากวาง เด็กๆ เข้าทำกัน
ถ้าอยากเข้าใจมากกว่านี้ เปิดใจศึกษาเรื่อง OOP ADO DAL BLL และ Business Logic ดู
ถ้าจะสร้าง control เองจริงๆ ต้องเอาแบบไม่รบกวนเวลาการทำงานส่วนในในการเขียนโปรแกรม
ทั้งโปรเจคจะดีกว่านะ
สิ่งที่เหมือนกัน==สิ่งที่เหมือนกัน(สืบทอดได้ ไม่นอกคอก ตามแม่เท่านั้น)
ทิ่งที่ไม่เหมือนกัน<>สิ่งที่เหมือนกัน (ทุกอย่างเหมือนกันแต่มีบางอย่างไม่เหมือนกัน สือทอดแต่นอกคอกได้)
ถ้าผมเขียนผิดพลาดประการใด ก็ขออภัยด้วยนะครับผม
Date :
2019-07-14 13:01:47
By :
บัญดิษฐ
ปัญหาหลัก
ต้องคิดเท่าไหร่ ผมไม่มีความเห็น (จะพิจารณาตาม ชญ - น้ำคำน้ำใจ - วิ่งได้อิสระ ฯลฯ + X)
ปัญหารอง
Delegate คืออะไร มีประโยชน์ยังไง ควรใช้เมื่อใด
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/delegates/
https://www.tutorialspoint.com/csharp/csharp_delegates
เมื่อเจอ Event
https://www.c-sharpcorner.com/UploadFile/84c85b/delegates-and-events-C-Sharp-net/
จำเป็นแค่ไหน? ถ้าจำเป็นต้องทำ callback (ในลิงค์มีตัวอย่าง ไม่พอสืบเพิ่มได้ครับ) ส่วน DI(M)U ตัดทิ้งไปได้เลยไม่มีทางทำได้ เพราะ การประกาศ delegate จำเป็นต้องมีจำนวนพารามิเตอร์เท่ากันและประเภทเดียวกันในตำแหน่งเดียวกันกับ Method/Event ซึ่งจากกรณีของคุณ Keydown กับ CellEnter มีอากิวเมนต์ 2 ไม่เหมือนกัน แม้จะสืบทอดมาจากคลาสแม่เดียวกันก็ตาม...ยังไม่นับรวมอีเวนต์อื่นที่จะถูกเพิ่มเข้ามาอีก
อย่าคิดลึกครับ
ปรับจาก NO.10 (C#)
public partial class Form1 : Form
{
// ไม่ต้องใส่ทั้ง static และ public
int rowIndex = -1;
public Form1()
{
InitializeComponent();
}
void SetGrid(DataGridView gd, int row)
{
dataGridView1.CellEnter += new DataGridViewCellEventHandler((object _sender, DataGridViewCellEventArgs _e) =>
{
// กดปุ่มอื่นก็ไม่ต้องโชว์(สำแดงครั้งเดียว)
if (rowIndex == -1)
MessageBox.Show("dgv.CellEnter += new DataGridViewCellEventHandler " + _e.RowIndex);
// rowIndex ตรงนี้ แจ้งเกิดใน Form1 จึงไม่ส่งผลต่อ FormN
rowIndex = _e.RowIndex;
});
}
private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
{
// เมื่อกด F12 อีเวนต์ CellEnter จะถูกมองข้าม
if (e.KeyCode == Keys.F12)
MessageBox.Show(" private void dataGridView1_KeyDown " + rowIndex);
}
private void Form1_Load(object sender, EventArgs e)
{
SetGrid(dataGridView1, rowIndex);
}
}
ผลลัพธ์ใน NO.18 ก็จะถูกเปลี่ยนเป็น 0 ทั้ง CellEnter และ Keydown...วิธีนี้สามารถนำไปใช้กับหลายอีเวนต์และหลายฟอร์ม โดยแต่ละฟอร์มเป็นอิสระต่อกัน...เพราะคุณไม่ได้ทำ Base Form แต่แจกแจงทุกฟอร์ม(?) ...แต่ถ้าทำเป็น Base Form ก็ลงลมปราณที่ Class อย่ามองข้าม Power ของ Class ครับ
ผมแค่มโน และเข้ามาให้กำลังใจทั้งผู้ส่งสารและผู้รับสาร ...Creation of Thailand & High Scruffing
ประวัติการแก้ไข 2019-07-14 21:24:33 2019-07-14 21:25:37
Date :
2019-07-14 21:22:01
By :
PhrayaDev
ในขณะที่เรา inherit มาใช้งาน เราสามารถปิด บาง feature ได้ หรือเพิ่ม feature ใหม่ลงไปได้
มันมีรูปแบบ overide overload ให้เราใช้งาน
มีชนิดตัวแปร ที่หลากหลายให้เราเลือกใช้งาน
เป็น static หรือ dynamic
เป็น global หรือ local
เป็น public หรือ private
ลองดู คห 22 ใหม่ ผมปรับโค๊ดเพิ่ม เพิ่มส่วนของ overide event button_click
Date :
2019-07-14 21:52:39
By :
Chaidhanan
ตัว DataGrid ประเด็นคือ
จะจับค่า KeyDown/KeyPress ตอนที่อยู่ใน Edit Mode ใช่ไหมครับ
ถ้าใช่ ลองดู event นี้ครับ
ProcessDataGridViewKey
ProcessDialogKey
แต่มันเขียนตรง ๆ ไม่ได้นะครับ
ต้อง inherit มาแก้เอา
http://theheing.blogspot.com/2012/05/datagridview-key-enter-cell.html
https://www.codeproject.com/Articles/34061/Cheating-the-DataGridView
https://stackoverflow.com/questions/1745943/datagridview-enter-key
Date :
2019-07-17 09:50:38
By :
fonfire
Load balance : Server 05