C#winform制作学生列表
学生列表
记录学习制作学生列表的过程。
准备数据源
建一个实体类,设置数据源的类型。可以新建一个文件夹Model,在它下面建一个Student.cs实体类。
Student.cs
namespace _1.窗体.Model
{
// 实体类:实体本质对现实的描述,映射ORM(Object Relation Mapping)
// POCO
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public bool Sex { get; set;}
public DateTime Birthday { get; set; }
public string Description { get; set; }
}
}
新建一个文件夹Data存放数据源,创建StudentData.cs类包含数据信息。
StudentData.cs
namespace _1.窗体.Data
{
public static class StudentData
{
// 1。数据源,数据的源类型已经准备 Student
public static List<Student> Students = new List<Student>() {
new Student(){ Id=1,Name="张三",Age=20,Sex=true,Birthday=new DateTime(2000,1,1),Description="个人描述"},
new Student(){ Id=2,Name="李四",Age=21,Sex=false,Birthday=new DateTime(2000,1,1),Description="个人描述"},
};
}
}
学生信息窗体
StudentForm.cs
先拖入控件,这里需要用到Lable(标签),TextBox(文本框),ComboBox(下拉框,用于选择性别等信息),DateTimePicker(日期时间选择器),Button(按钮),DataGridView(数据网格视图)。给相应的控件更改Text,Name,其中Name按小驼峰的风格去改,dtpBirthday,方便在写代码的时候认出来。
//窗体加载时的设置,窗体的Load事件构造函数执行
private void StudentForm_Load(object sender, EventArgs e)
{
// 性别默认选中“全部”
cbbSex.SelectedIndex = 0;
// 生日默认为空
dtpBirthdayStart.CustomFormat = " ";
dtpBirthdayEnd.CustomFormat = " ";
// 绑定数据源
BindDataGridView();
}
// 把数据源students和datagridview控件绑定一起。
private void BindDataGridView()
{
List<Student> filter = StudentData.Students;//绑定数据源给filter列表,等到按条件查询之后,会赋值给dataGridView的DataSource,实现数据网格绑定数据源。
//查询名字
//如果输入的名字匹配,则返回名字对应的学生信息,返回的类型是一个列表,并将结果存储在 filter 中。
if (!string.IsNullOrWhiteSpace(txtName.Text))
//筛选txtName.Text 不为空且不为仅包含空白字符的字符串。sNullOrEmpty仅检查空和null,而IsNullOrWhiteSpace还会考虑字符串中只包含空格的情况。
filter = filter.FindAll(stu1 => stu1.Name.Contains(txtName.Text));
//定义筛选的条件。Find() 获取第一个符合条件的元素并返回该元素,FindAll() 获取所有符合条件的元素,并最终返回一个列表。
//查询匹配的性别
if (cbbSex.SelectedIndex == 1) // 男
filter = filter.FindAll(stu => stu.Sex == false);
if (cbbSex.SelectedIndex == 2) // 女
filter = filter.FindAll(stu => stu.Sex);
//匹配生日信息,这样写可以看起来麻烦,但是有用。这样可以限定那个日期在规定的时间内。先转换为字符串,再转换成DataTime,大于start的stu对象以列表的形式赋给filter。
if (!string.IsNullOrWhiteSpace(dtpBirthdayStart.Text))
{
string date1 = DateTime.Parse(dtpBirthdayStart.Text).ToString("yyyy-MM-dd");
DateTime start = DateTime.Parse($"{date1} 00:00:00");
filter = filter.FindAll(stu => stu.Birthday >= start);
}
if (!string.IsNullOrWhiteSpace(dtpBirthdayEnd.Text))
{
string date1 = DateTime.Parse(dtpBirthdayEnd.Text).ToString("yyyy-MM-dd");
DateTime end = DateTime.Parse($"{date1} 23:59:59");
filter = filter.FindAll(stu => stu.Birthday <= end);
}
//改变行的高度,要求在绑定数据源之前设置行高才有效。(数据行)
dataGridView1.RowTemplate.Height = 30;
//先把上次绑定的数据源清除,再重新绑定,这样可以解决列表中数据已变化,但网格没有刷新的问题。数据网格的DataSource属性比较特殊,修改数据,数据源里面的变化不会自动更新。需要清理Clear()之后,再更新。
dataGridView1.DataSource = null;
dataGridView1.DataSource = filter.ToList();
//列宽平分
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
//改变标题的高度;
dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.EnableResizing;
dataGridView1.ColumnHeadersHeight = 30;
//改变行头宽度
dataGridView1.RowHeadersWidth = 30;
dataGridView1.RowHeadersVisible = true;
//改变背景
dataGridView1.BackgroundColor = Color.White;
// 更改列标题,获取列有两种方式:列名,列索引
//dataGridView1.Columns[0].HeaderText = "学生编号";
dataGridView1.Columns["Name"].HeaderText = "学生姓名";
dataGridView1.Columns["Age"].HeaderText = "年龄";
dataGridView1.Columns["Sex"].HeaderText = "性别";
dataGridView1.Columns["Birthday"].HeaderText = "出生日期";
dataGridView1.Columns["Description"].HeaderText = "个人描述";
// 格式化日期列 Default默认,Cell单元格
dataGridView1.Columns["Birthday"].DefaultCellStyle.Format = "yyyy-MM-dd HH:mm:ss";
dataGridView1.Columns["Id"].DefaultCellStyle.Format = "D2";
dataGridView1.Columns["Age"].DefaultCellStyle.Format = "0岁";
// 设置列的宽,Columns列,Rows行
dataGridView1.Columns["Id"].Width = 60;
// 设置列的显示或隐藏(可见性)
//dataGridView1.Columns[0].Visible = false;
}
// 查询按钮逻辑
private void btnSearch_Click(object sender, EventArgs e)
{
BindDataGridView(); // 点击查询时,调用此方法,绑定数据源
}
// 生日查询条件变化时,重新设置格式化,防止不能选择日期。
private void dtpBirthdayStart_ValueChanged(object sender, EventArgs e)
{
dtpBirthdayStart.CustomFormat = "yyyy-MM-dd";
}
private void dtpBirthdayEnd_ValueChanged(object sender, EventArgs e)
{
dtpBirthdayEnd.CustomFormat = "yyyy-MM-dd";
}
//添加一个学生
private void btnAdd_Click(object sender, EventArgs e)
{
AddStudentForm form = new AddStudentForm();
// 窗体对话框会返回一个结果,是个枚举值,常用的结果:OK,Cancel
// AddStudentForm窗体返回的结果。
DialogResult dialogResult = form.ShowDialog();
if (dialogResult == DialogResult.OK)
{
BindDataGridView();// 重新绑定数据源
}
}
private void btnClearBirthday_Click(object sender, EventArgs e)
{
// 清空生日选中的值,以便下次继续选择其他日期
dtpBirthdayStart.CustomFormat = " ";
dtpBirthdayEnd.CustomFormat = " ";
}
// 删除按钮逻辑
private void btnDelete_Click(object sender, EventArgs e)
{
if (dataGridView1.SelectedRows.Count == 0)
{
MessageBox.Show("请选择删除的行!", "提示框", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (dataGridView1.SelectedRows.Count > 1)
{
MessageBox.Show("一次只能删除一个!", "提示框", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
int id = (int)dataGridView1.SelectedRows[0].Cells["Id"].Value;
DialogResult dialogResult = MessageBox.Show($"你确定要删除Id={id}这条数据吗?", "询问", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (dialogResult == DialogResult.Yes)
{
//Student student = StudentData.Students.Find(stu => stu.Id == id);
//StudentData.Students.Remove(student);如果没有找到匹配的对象,Find 方法会返回 null ,此时直接调用 Remove 可能会导致运行时错误。
int index = StudentData.Students.FindIndex(stu => stu.Id == id);
StudentData.Students.RemoveAt(index);
BindDataGridView();
}
}
// 修改按钮逻辑
private void btnUpdate_Click(object sender, EventArgs e)
{
// SelectedRows选中行
if (dataGridView1.SelectedRows.Count == 0)
{
MessageBox.Show("请选择修改的行!", "提示框", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (dataGridView1.SelectedRows.Count > 1)
{
MessageBox.Show("一次只能修改一个!", "提示框", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// 拿到一行中主键(唯一),拿到学生Id Cells["Id"].Value拿到某个单元格的值,值有装箱操作,使用时拆箱。
int id = (int)dataGridView1.SelectedRows[0].Cells["Id"].Value;
EditStudentForm editStudentForm = new EditStudentForm(id);
DialogResult dialogResult = editStudentForm.ShowDialog();
if (dialogResult == DialogResult.OK)
{
BindDataGridView();// 重新绑定数据源
}
}
//修改性别和年龄的显示样式,性别修改不成功。
private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
//if (e.RowIndex != -1 && e.ColumnIndex == 3) // 性别
if (this.dataGridView1.Columns[e.ColumnIndex].Name == "Sex")
{
bool sex = e.Value.ToString() == "True";
Debug.WriteLine(sex ? "女" : "男");
//e.Value = sex ? "女" : "男";在列表中是一个复选框的样式,不能修改成字符串。
}
if (this.dataGridView1.Columns[e.ColumnIndex].Name == "Age")
{
e.CellStyle.ForeColor = Color.Green;
e.Value = e.Value.ToString() + "岁";
}
}
添加学生窗体
AddStudentForm.cs
private void AddStudentForm_Load(object sender, EventArgs e)
{
// 练习集合
//cbbSex.Items.Add("hello");
cbbSex.Items.Insert(0, "请选择...");
// 默认选中的索引
cbbSex.SelectedIndex = 0;
}
private void btnSave_Click(object sender, EventArgs e)
{
//1.校验数据 永远不要相信用户输入
#region 数据校验
if (string.IsNullOrWhiteSpace(txtName.Text))
{
MessageBox.Show("请输入学生姓名!", "提示框", MessageBoxButtons.OK, MessageBoxIcon.Information);
txtName.Focus(); // 让学生姓名输入框获取焦点
return;
}
if (!(nudAge.Value >= 18 && nudAge.Value <= 65))
{
MessageBox.Show("年龄要求在[18-65]岁之间!", "提示框", MessageBoxButtons.OK, MessageBoxIcon.Information);
nudAge.Focus();
return;
}
if (cbbSex.SelectedIndex == 0)
{
MessageBox.Show("请选择性别!", "提示框", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
if (string.IsNullOrWhiteSpace(dtpBirthday.Text))
{
MessageBox.Show("请选择生日!", "提示框", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
else
{
int year1 = DateTime.Now.Year;
int year2 = dtpBirthday.Value.Year;
int age = int.Parse(nudAge.Value.ToString());
if (year1 - year2 != age)
{
MessageBox.Show("生日和年龄不匹配!", "提示框", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
}
if (string.IsNullOrWhiteSpace(rtbDescription.Text))
{
MessageBox.Show("请填写个人描述!", "提示框", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
#endregion
int count = StudentData.Students.Count; // 拿列表项的数量(长度)
int maxIndex = count - 1; // 最后一个项的索引(最大索引)
Student lastStudent = StudentData.Students[maxIndex]; // 拿到列表中最后一个学生
int maxId = lastStudent.Id;
Student oneStudent = new Student()
{
Id = maxId + 1,
Name = txtName.Text,
Age = int.Parse(nudAge.Value.ToString()),
Sex = cbbSex.SelectedText == "男" ? false : true,
Birthday = dtpBirthday.Value,
Description = rtbDescription.Text,
};
StudentData.Students.Add(oneStudent);
// 给另外一个窗体返回结果。默认行为:当前窗体会关闭
DialogResult = DialogResult.OK;
}
修改学生窗体
EditStudentForm.cs
public partial class EditStudentForm : Form
{
// 存储要编辑学生的Id,拿到Id目的为了拿学生实体(模型)
private int editId = 0;
public EditStudentForm(int id)
{
InitializeComponent();
editId = id;
}
// 窗体加载后,先把编辑学生原来信息显示到界面
private void EditStudentForm_Load(object sender, EventArgs e)
{
if (editId != 0)
{
//Student editStudent = StudentData.Students.Find(stu => stu.Id == editId);
Student editStudent = StudentData.Students.Where(stu => stu.Id == editId).ToList()[0];
// 把学生实体相应的属性赋值给相应的控件。注意细节:类型
txtName.Text = editStudent.Name;
nudAge.Value = editStudent.Age;
rbBoy.Checked = editStudent.Sex == false;
rbGril.Checked = editStudent.Sex == true;
dtpBirthday.Value = editStudent.Birthday; // dtpBirthday.Text
//dtpBirthday.Text = editStudent.Birthday.ToString("yyyy-MM-dd");
rtbDescription.Text = editStudent.Description;
}
}
private void btnSave_Click(object sender, EventArgs e)
{
// 校验省略
#region 数据校验
if (string.IsNullOrWhiteSpace(txtName.Text))
{
MessageBox.Show("请输入学生姓名!", "提示框", MessageBoxButtons.OK, MessageBoxIcon.Information);
txtName.Focus(); // 让学生姓名输入框获取焦点
return;
}
if (!(nudAge.Value >= 18 && nudAge.Value <= 65))
{
MessageBox.Show("年龄要求在[18-65]岁之间!", "提示框", MessageBoxButtons.OK, MessageBoxIcon.Information);
nudAge.Focus();
return;
}
if (string.IsNullOrWhiteSpace(dtpBirthday.Text))
{
MessageBox.Show("请选择生日!", "提示框", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
else
{
int year1 = DateTime.Now.Year;
int year2 = dtpBirthday.Value.Year;
int age = int.Parse(nudAge.Value.ToString());
if (year1 - year2 != age)
{
MessageBox.Show("生日和年龄不匹配!", "提示框", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
}
if (string.IsNullOrWhiteSpace(rtbDescription.Text))
{
MessageBox.Show("请填写个人描述!", "提示框", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
#endregion
// 编辑学生(修改)
// 拿到编辑学生的索引
int index = StudentData.Students.FindIndex(stu=>stu.Id == editId);
// 产生一个新学生,注意:新学生和原来的学生有一个地方不变:编号Id
Student newStudent = new Student() {
Id = editId,
Name = txtName.Text,
Age = int.Parse(nudAge.Value.ToString()),
Sex = rbGril.Checked,
Birthday = dtpBirthday.Value,
Description = rtbDescription.Text,
};
StudentData.Students[index] = newStudent;
DialogResult = DialogResult.OK;
}
}