员工打卡案例 (泛型集合) (2018年4月4号)鹅毛大雪的背后还有苦逼的努力
1.首先是需要的窗体和类

2.主窗体Main里面需要做的事情(代码块)
//定义了泛型集合List<SE>
public List<SE> list = new List<SE>();
private void 新增ToolStripMenuItem_Click(object sender, EventArgs e)
{
//实例化增加的窗体对象
FrmInsert fi = new FrmInsert();
//通过this.调用当前对象的属性或者方法,
fi.fm = this;
//显示增加窗体
fi.Show();
}
private void 打卡记录ToolStripMenuItem_Click(object sender, EventArgs e)
{
FrmDaKa fd = new FrmDaKa();//创建打卡窗体的对象
fd.dic = this.dic;//通过this.调用当前对象的属性或者方法。
fd.Show();//显示打卡的窗体
}
private void FrmMain_Load(object sender, EventArgs e)
{
}
//刷新的方法,把List集合当参数传递
public void BindGrid(List<SE> list)
{
//绑定当前DataGridView上
this.dgvList.DataSource = new BindingList<SE>(list);
}
private void 删除ToolStripMenuItem_Click(object sender, EventArgs e)
{
#region 删除方法
//使用DialogResult类型接受返回值
DialogResult result = MessageBox.Show("确定删除吗?", "提示", MessageBoxButtons.OKCancel);
//判断用户的选择
if (result == DialogResult.OK)
{
//获取当前选中的用户选中的列进行删除
string num = dgvList.SelectedRows[0].Cells[0].Value.ToString();
//循环打印集合中的元素
for (int i = 0; i < list.Count; i++)
{
//判断集合的第i位的ID是否和选中的ID一致
if (list[i].ID == num)
{
//删除对象
list.Remove(list[i]);
//调用绑定数据源的方法重新绑定数据源
BindGrid(list);
//提示语句
MessageBox.Show("删除成功!", "提示");
}
}
}
#endregion
}
private void 修改ToolStripMenuItem_Click(object sender, EventArgs e)
{
}
private void btnSelect_Click(object sender, EventArgs e)
{
#region 模糊查询
//定义泛型List<SE>类型的临时集合
List<SE> temp = new List<SE>();
//foreach循环原始集合list,类型为SE
foreach (SE item in list)
{
//判断是否有返回值,并且通过ID来模糊查询,使用到了IndexOf方法
if (item.ID.IndexOf(this.txtID.Text.Trim()) != -1)
{
//绑定到临时集合中
temp.Add(item);
}
}
//重新绑定数据源
this.dgvList.DataSource = new BindingList<SE>(temp);
#endregion
}
//实例化双列集合Dictionary。Key为字符串类型,Record类为它的值
public Dictionary<string, Record> dic = new Dictionary<string, Record>();
private void 签到ToolStripMenuItem_Click(object sender, EventArgs e)
{
//判断选中的行是否大于0
if (this.dgvList.SelectedRows.Count < 1)
{
//给用户提示。
MessageBox.Show("请选中一行!");
return;
}
//获取DataGridView选中的值。
string workNo = dgvList.CurrentRow.Cells[0].Value.ToString();
//循环string类型的键
foreach (string id in dic.Keys)
{
//判断选中的值和id是否相同
if (workNo == id)
{
//如果相同就证明已经签到过了
MessageBox.Show("您已经签到过了!");
return;
}
}
//实例化Record类的对象
Record record = new Record();
//把选中的值给ID
record.ID = workNo;
//将选中的值给变量name
record.Name = dgvList.CurrentRow.Cells[1].Value.ToString();
//获取当前本机上的时间。
record.SignInTime = DateTime.Now;
//添加到双列集合Dictionary中,ID为键,整个对象为值
this.dic.Add(record.ID,record);
//提示用户
MessageBox.Show("签到成功!");
}
private void 签退ToolStripMenuItem_Click(object sender, EventArgs e)
{
//判断选中的行数是否大于1,并提示
if (this.dgvList.SelectedRows.Count < 1)
{
MessageBox.Show("请选中一行!");
return;
}
//将选中的值赋给变量ID
string ID = dgvList.CurrentRow.Cells[0].Value.ToString();
//定义布尔变量,为false
bool isOut = false;
//循环Key键
foreach (string key in dic.Keys)
{
//判断是否相等
if (key == ID)
{
//签退的时间,并提示
this.dic[key].SignOutTime = DateTime.Now;
MessageBox.Show("签退成功!");
//布尔变量改为true并退出。
isOut = true;
break;
}
}
//判断还没有签到就签退。
if (!isOut)
{
MessageBox.Show("很抱歉,尚未签到!");
}
}
3.添加员工信息的窗体(代码块)
private void btnInsert_Click(object sender, EventArgs e)
{
Insert();//添加的方法
}
public FrmMain fm;//创建公共的窗体类型变量
private void Insert()
{
//异常处理
try
{
//实例化SE类对象
SE se = new SE();
//拿到文本框的值赋给ID
se.ID = txtID.Text.Trim();
//拿到文本框的值赋给Name
se.Name = txtName.Text.Trim();
//拿到文本框的值赋给Age
se.Age =Convert.ToInt32(txtAge.Text.Trim());
//判断选中的值是否等于男
if (this.cboSex.SelectedItem.ToString() == "男")
{
se.Sex = Enum.男;
}
else
{
se.Sex = Enum.女;
}
//循环集合list,类型为SE
foreach (SE item in fm.list)
{
//判断工号是否已经存在,并提示
if (item.ID == se.ID)
{
MessageBox.Show("此工号已经存在");
return;
}
}
//添加到集合中
fm.list.Add(se);
//关闭窗体
this.Close();
}
catch (Exception ex)
{
//异常提示
MessageBox.Show("出错:"+ex.Message);
}
finally
{
//调用绑定数据源的方法
fm.BindGrid(fm.list);
}
}
4.打卡窗体(代码块)
//定义Dictionary属性
public Dictionary<string, Record> dic {get;set; }
private void FrmDaKa_Load(object sender, EventArgs e)
{
//使没有绑定数据源的值不显示在DataGridView上
dgvList.AutoGenerateColumns = false;
//实例化BindingSource对象
BindingSource bs = new BindingSource();
//先绑定在BindingSource对象的数据源上
bs.DataSource = dic.Values;
//在绑定DataGridView上
this.dgvList.DataSource = bs;
//调用共有多少条记录的方法
Rows();
}
public void Rows()
{
//获取DataGridView上的行数
int row = dgvList.RowCount;
//拼接到Label标签上
this.lblName.Text = "共有"+row+"条打印记录";
}
5.接下来说一下这是案例的难点和重点
01.//刷新的方法,把List集合当参数传递
public void BindGrid(List<SE> list)
{
//绑定当前DataGridView上
this.dgvList.DataSource = new BindingList<SE>(list);
}
BindGrid方法是把泛型集合List<SE>作为参数来传递,类型为SE,也是员工类,这个方法主要是做刷新的操作,当添加完员工后调用该方法,实现刷新功能。
02.通过公共对象进行调用当前对象的属性或者方法。
FrmDaKa fd = new FrmDaKa();//创建打卡窗体的对象
fd.dic = this.dic;//通过this.调用当前对象的属性或者方法。
fd.Show();//显示打卡的窗体
通过定义打卡窗体的公共对象,可以直接this把本窗体的属性和方法传递过去
03.拿到选中的值
record.Name = dgvList.CurrentRow.Cells[1].Value.ToString();

其实这块有点小尴尬,当打卡窗体要拿到主窗体的员工姓名的时候出来了一个小问题,首先我们看一下截图,这是正确的定义属性为的方法。

这样看我们可以看到姓名这一列如果按索引来看的话应该是1,但是出现了一个小问题

这是把姓名的属性放到了第三位上去,但是输出结果就不一样了。

我们可以看到这次的输出结果为23,正是年龄的结果,因此我们调试了半天才出来正确的结果。
我在这里就简单的说一下这个,可能对你们以后发生这样的问题的时候容易解决吧。
属性的定义与你在主窗体想打卡窗体传值得时候它的下标发生了变化,与你在SE员工类里面定义属性定义的位置相等了,所以本来为1的下标就能拿到姓名的值,却被下标2拿到了姓名的值。
注意一下就好,如果你窗体拿错值得时候别忘了看一下定义属性的位置是否一致。
浙公网安备 33010602011771号