C#winform製作學生列表

海域發表於2024-08-16

學生列表

記錄學習製作學生列表的過程。

準備資料來源

​ 建一個實體類,設定資料來源的型別。可以新建一個資料夾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,方便在寫程式碼的時候認出來。

1723811748021


	//窗體載入時的設定,窗體的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

1723813744762


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

1723813767100


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;
     }
 }
 

相關文章