1.需要用到的窗体和类
主窗体代码
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace StaffCheck { public partial class FrmMain : Form { public FrmMain() { InitializeComponent(); } //列表,保存SE对象 public List<SE> programmerList = new List<SE>(); //打卡记录Dictionary public Dictionary<string, Record> RecordList = new Dictionary<string, Record>(); //新增员工窗体 private void toolStripLabel1_Click(object sender, EventArgs e) { //新增员工窗体 FrmInsert fl = new FrmInsert(); //维护类型 ,1表示新增,0表示修改 //fl.MaintanceType = 1; fl.FrmParent = this;//this就是获得当前的对象,通过this.调用当前对象的属性或者方法, fl.Show(); } //刷新DataGridView数据 public void BindGrid(List<SE> list) { this.dgvStaffInfo.DataSource = new BindingList<SE>(list); } private void btnSrarch_Click(object sender, EventArgs e) { //查看,支持模糊查询 List<SE> tempList = new List<SE>();//用临时列表保存查询到的信息 foreach (SE item in this.programmerList) { if (item.Id.IndexOf(this.txtId.Text.Trim())!=-1) { tempList.Add(item); } } this.dgvStaffInfo.DataSource = new BindingList<SE>(tempList); } private void dgvStaffInfo_CellContentClick(object sender, DataGridViewCellEventArgs e) { } //点击删除按钮 private void toolStripLabel3_Click(object sender, EventArgs e) { //是否选中一行 if (this.dgvStaffInfo.SelectedRows.Count > 0) { DialogResult choice = MessageBox.Show("确定要删除吗?", "提示", MessageBoxButtons.OKCancel); if (choice == DialogResult.OK) { //拿到选中的员工号进行删除 string id = this.dgvStaffInfo.SelectedRows[0].Cells[0].Value.ToString(); for (int i = 0; i < programmerList.Count; i++) { if (programmerList[i].Id == id) { //执行删除操作 programmerList.Remove(programmerList[i]); //刷新DataGridView BindGrid(programmerList); MessageBox.Show("删除成功!"); } } } else { MessageBox.Show("请选择一行!"); return; } } } private void FrmMain_Load(object sender, EventArgs e) { //初始化信息 initial(); } /// <summary> /// 初始化信息 /// </summary> private void initial() { programmerList.Add(new SE() { Id = "1", Name = "蛮子", Age = 28, Gender = Gender.男.ToString() }); programmerList.Add(new SE() { Id = "2", Name = "光辉", Age = 30, Gender = Gender.女.ToString() }); programmerList.Add(new SE() { Id = "3", Name = "皇子", Age = 34, Gender = Gender.男.ToString() }); this.dgvStaffInfo.DataSource = new BindingList<SE>(programmerList); } //签到 private void 签到ToolStripMenuItem_Click(object sender, EventArgs e) { //验证有选中的一行 if (this.dgvStaffInfo.SelectedRows.Count > 0) { //确保没有签过到 string qiandao = this.dgvStaffInfo.SelectedRows[0].Cells[0].Value.ToString(); //MessageBox.Show(qiandao); foreach (string id in RecordList.Keys) { if (qiandao==id) { MessageBox.Show("您已经签过到!"); return; } } //执行签到 Record record = new Record(); record.ID = qiandao; record.Name = dgvStaffInfo.SelectedRows[0].Cells[1].Value.ToString(); record.SignInTime = DateTime.Now;//获取系统当前时间 this.RecordList.Add(record.ID,record);//添加到签到记录 MessageBox.Show("签到成功!"); } else { MessageBox.Show("请选中一行!"); return; } } private void toolStripLabel4_Click(object sender, EventArgs e) { //打卡记录 //绑定数据源,显示Dictionary FrmRecord fr = new FrmRecord(); fr.RecordList = this.RecordList;//t获得当前的对象,通过this.调用当前对象的属性或者方法, fr.Show(); } //签退 private void 签退ToolStripMenuItem_Click(object sender, EventArgs e) { //签退操作 //确保有选中的行 if (this.dgvStaffInfo.SelectedRows.Count > 0) { string ID = dgvStaffInfo.CurrentRow.Cells[0].Value.ToString(); bool isOut = false;//标志是否已经签过到 foreach (string key in RecordList.Keys) { if(key==ID) { //执行签到,设置签退时间 this.RecordList[key].SignOutTime = DateTime.Now;//获得当前系统时间,也就是签退的时间 MessageBox.Show("签退成功"); isOut = true; break; } } if (!isOut) { MessageBox.Show("很抱歉尚未签到!"); } } else { MessageBox.Show("请选中一行!"); return; } } } }
添加窗体代码
public partial class FrmInsert : Form { //保存父窗体的引用 public FrmMain FrmParent { get; set; } public FrmInsert() { InitializeComponent(); this.cbSex.SelectedIndex = 0;//初始化,显示男 } private void button1_Click(object sender, EventArgs e) { //单击保存按钮 save(); } /// <summary> /// 保存 /// </summary> private void save() { try { //输入处理 SE pr = new SE();//员工类 pr.Id = this.txtId.Text.Trim();//工号 pr.Name = this.txtName.Text.Trim();//姓名 pr.Age = Int32.Parse(this.txtAge.Text.Trim());//年龄 if (this.cbSex.SelectedItem.ToString() == "男")//性别 { pr.Gender = Gender.男.ToString(); } else { pr.Gender = Gender.女.ToString(); } //添加操作 //工号唯一性验证 foreach (SE item in FrmParent.programmerList) { if (item.Id == pr.Id) { MessageBox.Show("此工号已经存在!"); return; } } FrmParent.programmerList.Add(pr);//将输入的信息添加到集合中 this.Close(); } catch (Exception ex) { MessageBox.Show("异常!" + ex.Message); } finally { //刷新父窗体的信息 this.FrmParent.BindGrid(FrmParent.programmerList); } } private void FrmInsert_Load(object sender, EventArgs e) { } }
打卡记录窗体代码
public partial class FrmRecord : Form { public FrmRecord() { InitializeComponent(); } public FrmMain fm{get;set;}//主窗体对象 public Dictionary<string, Record> RecordList; private void FrmRecord_Load(object sender, EventArgs e) { this.dgvRecords.AutoGenerateColumns = false;//去掉多余的列 //打卡记录 //绑定数据源,显示Dictionary BindingSource bs = new BindingSource(); bs.DataSource =RecordList.Values; this.dgvRecords.DataSource = bs; Rows();//打印行数 } /// <summary> /// 打印显示行数 /// </summary> public void Rows() { int row = this.dgvRecords.RowCount;//拿到行数 this.laNumber.Text = "共有" + row + "条打卡记录"; } private void dgvRecords_CellContentClick(object sender, DataGridViewCellEventArgs e) { } }
遇到的难点及问题
1.使用单列泛型集合(List<T>)绑定DataGridView,可以直接绑定,这里使用集合作为参数
public void BindGrid(List<SE> list)
{
this.dgvprogrammer.DataSource = new BindingList<SE>(list)//绑定list集合到dgvprogrammer
}
2.添加完成以后,关闭添加窗体,并刷新父窗体。
在finally中重新绑定以下数据源即可。
3.根据员工工号模糊查询。
用string类的IndexOf( )方法实现模糊查询
List<SE> tempList = new List<SE>( );//用临时集合保存查询到的信息
foreach(SE item in this.programmerList)
{
if(item.ID.IndexOf(this.txtID,Text.Trim()!=-1))//indexof() :在字符串中从前向后定位字符和字符串;所有的返回值都是指在字符串的绝对位置,如为空则为- 1,如果有就将其遍历出来
{
tempList.Add(item);
}
}
this.dgvprogrammer.DataSource = new BindingList<SE>(tempList);//重新绑定到DataGridView上
4.DataGridView控件显示Dictionary集合(双列集合)中的数据,不能直接绑定。
BindingSource bs = new BindingSource();//绑定源
bs.DataSource =recordList.Values;//拿到集合中的Value;
this.dgvRecords.DataSource=bs;//绑定到DatatGridView上。
5.关于在用索引拿DataGridView中选中一行的值时出现的拿错值的问题。
如。this.DataGridView.SelectedRows[0].Cells[0].Value;为什么尽量用列名去拿,如:this.DataGridView.SelectedRows[0].Cells[“Name”].Value;
因为在拿选中行的值的时候你封装字段的顺序是会影响用索引拿值,经过打断点测试,确实如此。
6.关于重复签退的问题
每个员工在每天应该只能签退一次。