學生列表
記錄學習製作學生列表的過程。
準備資料來源
建一個實體類,設定資料來源的型別。可以新建一個資料夾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;
}
}