Я предполагаю, что поле «ExpireDate», возвращаемое из запроса sql, является объектом DateTime
.Если это так, то может показаться, что преобразование «даты» в строку не требуется.Например, учитывая «будущую» дату, тогда разница между сегодняшней датой и «будущей» датой может быть получена как…
TimeSpan dif = futureDate.Subtract(DateTime.Now);
Использование DataTable
дает возможность использовать столбец Expression
Однако я не думаю, что это будет работать с датами и временем.К счастью, это не должно быть сложно реализовать, если сетка DataSource
является DataTable
.Использование «Класса» было бы другим вариантом.Этот пример использует DataTable
как DataSource
для сетки.
Учитывая это, для простоты может показаться, что метод, который берет DataRow
из таблицы данных и добавляет это TimeSpan
разница может пригодиться.Это может выглядеть примерно так:
private void SetDifCol(DataRow row) {
TimeSpan dif = ((DateTime)row["ExpireDate"]).Subtract(DateTime.Now);
row["TimeToExpire"] = dif.Days + " days " + dif.Hours + " hours " + dif.Minutes + " minutes";
}
Учитывая, что DataTable
уже заполнен данными ... код должен будет "ДОБАВИТЬ" этот столбец различий, а затем перебрать каждую строку ирассчитать разницу между датами.Поэтому небольшой метод, который просто добавляет этот столбец, может выглядеть примерно так:
private void AddDifferenceColumn(DataTable dt) {
dt.Columns.Add("TimeToExpire", typeof(string));
}
Далее идет цикл по всем строкам в DataTable
и просто вызывается метод SetDifCol
в каждой строке.
private void CalculateDateDif(DataTable dt) {
foreach (DataRow row in dt.Rows) {
SetDifCol(row);
}
}
Это будет работать, как и ожидалось, при загрузке данных, однако, что если пользователь «изменит» одно из значений «ExpireDate» в сетке?В этом случае нам нужно подключить одно из событий смены ячеек сетки.В частности, сетки CellValueChanged
событие.Это событие вызовет метод SetDifCol
, если значение «ExpireDate» изменится в этой строке…
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e) {
if (dataGridView1.Columns[e.ColumnIndex].Name == "ExpireDate") {
if (e.RowIndex >= 0 && dataGridView1.Rows[e.RowIndex].Cells["ExpireDate"].Value != null) {
DataRowView row = (DataRowView)dataGridView1.Rows[e.RowIndex].DataBoundItem;
SetDifCol(row.Row);
}
}
}
Соединение всего этого вместе может выглядеть примерно так: *
DataTable GridTable;
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
GridTable = GetTable();
FillTable(GridTable);
AddDifferenceColumn(GridTable);
CalculateDateDif(GridTable);
dataGridView1.DataSource = GridTable;
dataGridView1.Columns[3].Width = 180;
}
private DataTable GetTable() {
DataTable dt = new DataTable();
dt.Columns.Add("ID", typeof(string));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("ExpireDate", typeof(DateTime));
return dt;
}
private void AddDifferenceColumn(DataTable dt) {
dt.Columns.Add("TimeToExpire", typeof(string));
}
private void FillTable(DataTable dt) {
dt.Rows.Add("ID1", "Name1", new DateTime(2019, 12, 31));
dt.Rows.Add("ID2", "Name2", new DateTime(2019, 8, 31));
dt.Rows.Add("ID3", "Name3", new DateTime(2019, 4, 30));
dt.Rows.Add("ID4", "Name4", new DateTime(2019, 1, 31));
dt.Rows.Add("ID5", "Name5", new DateTime(2019, 4, 12, 21, 38, 00));
}
private void CalculateDateDif(DataTable dt) {
foreach (DataRow row in dt.Rows) {
SetDifCol(row);
}
}
private void SetDifCol(DataRow row) {
TimeSpan dif = ((DateTime)row["ExpireDate"]).Subtract(DateTime.Now);
row["TimeToExpire"] = dif.Days + " days " + dif.Hours + " hours " + dif.Minutes + " minutes";
}
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e) {
if (dataGridView1.Columns[e.ColumnIndex].Name == "ExpireDate") {
if (e.RowIndex >= 0 && dataGridView1.Rows[e.RowIndex].Cells["ExpireDate"].Value != null) {
DataRowView row = (DataRowView)dataGridView1.Rows[e.RowIndex].DataBoundItem;
SetDifCol(row.Row);
}
}
}
Надеюсь, это поможет.
РЕДАКТИРОВАТЬ: изменить тип столбца с string
на int
для числовой сортировки.
В отношении дополнительного вопроса, который вы разместили, вы прокомментировали, что «я хочу вычислить в соответствии с тем, что находится внутри моей таблицы БД» … В этом вопросе или другом вопросе нет кода, который показываетбаза данных.Как вы получаете данные для начала?
В этом вопросе появляется НОВЫЙ DataTable
dt
и к нему добавляется столбец, однако он НИКОГДА не используется.Цикл в коде просто добавляет столбец различий к «GRID», а НЕ DataTable.
Мой ответ «добавляет» столбец diffence к DataTable
(что вам следует сделать).Я рекомендую вам показать, как вы получаете данные из базы данных.
Что касается сортировки столбца, вы уже заметили, что string
, которые являются числами, не будут правильно сортироваться численно.Это потому, что они строки ... решение ... сделать их ints
.Используя мой ответ, для этого нужны два изменения.Во-первых, создание столбца должно быть типа int
...
private void AddDifferenceColumn(DataTable dt) {
dt.Columns.Add("TimeToExpire", typeof(int));
}
Во-вторых, необходимо изменить метод SetDifCol
.Поскольку требуется только разность дней, а любые значения, меньшие нуля, должны отображаться как ноль (0), следующие изменения должны соответствовать этому требованию.
private void SetDifCol(DataRow row) {
TimeSpan dif = ((DateTime)row["ExpireDate"]).Subtract(DateTime.Now);
if (dif.Days >= 0) {
row["TimeToExpire"] = dif.Days;
}
else {
row["TimeToExpire"] = 0;
}
}
Эти два изменения должны отсортировать столбец численно, как и ожидалось.
Наконец, должно быть ясно, что ЕСЛИ вы хотите, чтобы этот столбец «различий» был отражен в базе данных… тогда вам нужно будет добавить столбец различий в таблицу базы данных, ТО, вам нужно будет выполнитькоманда обновления таблицы базы данных.