简体   繁体   中英

Set value as age instead of date of birth in a datagridview column

I have a DataGridview in a windows forms. I have a field DOB (Date Of Birth) as DateTime, I want to display Age instead of displaying the DOB. Example: DOB is 13.06.2007 I want to display 10. I have a method that calculates the age from the DOB, how can i assign it to the coulmn. ?

private void bindToGrid(DataTable dtb)
{
   using (dtb)
   {
       dataGridView1.DataSource = dtb;

       dataGridView1.Columns[2].Name = "Age";
       dataGridView1.Columns[2].HeaderText = "Age";
       dataGridView1.Columns[2].DataPropertyName = "DOB";
    }
}

public static string getAge(DateTime dob)
{
    var today = DateTime.Today;
    var age = today.Year - dob.Year;

    if (dob > today.AddYears(-age))
        age--;
    return age.ToString();
}

If the DataGridView has a DataTable as a DataSource such that the “DOB” column in the DataTable is of type DateTime , then you will not be able to put an int “Age” value into those cells of the DataGridView because this will throw a DataError since the single int (Age) value is not in a valid DateTime format.

Since “Age” is a calculated value, and we can always calculate this value based on the birth date, then in seems unnecessary to go through the trouble of changing the current DataTable dtb “DOB” column to an “Age” column. In addition altering the table may affect other code if the altered table is used elsewhere and expects a DOB field. Therefore, it makes sense to keep this “Age” column separate from the DataTable and simply ADD this “Age” column to the DatGridView .

To keep things simple, and to get you started, I would recommend you leave the “DOB” column in the DataTable alone for the time being and simply ADD this “Age” column to the DataGridView NOT the DataTable .

Assuming the DataGridView is already filled with data dataGridView1.DataSource = dtb; …The method below AddAgeColumn adds the “Age” column then loops through the DataGridView rows and sets the “Age” columns value using the getAge method in the original post. You would call this method right after the grid is filled with data.

private void AddAgeColumn() {
  try {
    dataGridView1.Columns.Add("Age", "Age");
    DateTime curBD;
    int curAge;
    foreach (DataGridViewRow dgvr in dataGridView1.Rows) {
      if (!dgvr.IsNewRow) {
        curBD = (DateTime)dgvr.Cells["DOB"].Value;
        curAge = getAge(curBD);
        dgvr.Cells["Age"].Value = curAge;
      }
    }
  }
  catch (Exception e) {
    MessageBox.Show("Error: " + e.Message);
  }
}

This should display both the “DOB” column and the “Age” column in the grid. The only problem is if the user either adds a new row or changes a “DOB” value, then the “Age” column may not reflect this change. To fix this, we simply need to add a method that looks for when the “DOB” value changes and when it does, simply update the “Age” column. The DataGridView 's CellValueChanged event will work for indicating if the “DOB” value is changed. A wired up example is below:

private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e) {
  if (dataGridView1.Columns[e.ColumnIndex].Name == "DOB") {
    if (!String.IsNullOrEmpty(dataGridView1.Rows[e.RowIndex].Cells["DOB"].Value.ToString())) {
      DateTime newDOB = (DateTime)dataGridView1.Rows[e.RowIndex].Cells["DOB"].Value;
      dataGridView1.Rows[e.RowIndex].Cells["Age"].Value = getAge(newDOB); ;
    } else {
      dataGridView1.Rows[e.RowIndex].Cells["Age"].Value = "";
    }
  }
}

Lastly, this will work however, if the user is running the program at 11:59 PM, and one of the “DOB” values is the current date… then when the clock reaches 12:00 AM the AGE will not reflect this change since the “DOB” value has not changed. You may consider a method to update the “Age” values and simply run it if this situation occurs. Hope this makes sense and helps.

I think you have to introduce a new property:

  1. add a new property to the object that binds to the datagridview table, call it "Age"
  2. make DOB property not browsable by adding an attribute [Browserable(false)], so it won't visually appear in the table
  3. put logic in 'Age' setter to update DOB value whenever Age value is changed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM