Формат TimeSpan в столбце DataGridView
Я видел Эти Вопросы , но оба включают методы, которые недоступны в значении формата CellStyle. Я хочу показать только часть часов и минут (16: 05), а не секунды (16:05:13). Я попытался заставить значение секунд равняться нулю, но все равно получилось что-то вроде 16:05:00. Если не использовать kludge, например, предоставляя строку или DateTime (и только показывая часть часа / минуты), есть ли способ заставить форматирование делать то, что я хочу.
5 ответов:
Я просто убедился в этом сам. К сожалению, решение довольно сложное. Хорошая новость в том, что это работает.
Во-первых, вам нужна реализацияICustomFormatter
, которая имеет дело со значениямиTimeSpan
. Платформа .NET framework не включает такой тип out-of-box; я предполагаю это потому, что Microsoft не хотела иметь дело с неоднозначностью, связанной с форматированиемTimeSpan
(например, означает ли "hh" общее количество часов или только часовой компонент?) и последовавший за этим натиск поддержки проблемы, которые возникнут, когда эти неясности смутят разработчиков.Это нормально - просто реализуйте свои собственные. Ниже приведен пример класса, который я написал, который использует в основном те же строки пользовательского формата, что и
DateTime
(те, которые были применимы, во всяком случае)*:class TimeSpanFormatter : IFormatProvider, ICustomFormatter { private Regex _formatParser; public TimeSpanFormatter() { _formatParser = new Regex("d{1,2}|h{1,2}|m{1,2}|s{1,2}|f{1,7}", RegexOptions.Compiled); } #region IFormatProvider Members public object GetFormat(Type formatType) { if (typeof(ICustomFormatter).Equals(formatType)) { return this; } return null; } #endregion #region ICustomFormatter Members public string Format(string format, object arg, IFormatProvider formatProvider) { if (arg is TimeSpan) { var timeSpan = (TimeSpan)arg; return _formatParser.Replace(format, GetMatchEvaluator(timeSpan)); } else { var formattable = arg as IFormattable; if (formattable != null) { return formattable.ToString(format, formatProvider); } return arg != null ? arg.ToString() : string.Empty; } } #endregion private MatchEvaluator GetMatchEvaluator(TimeSpan timeSpan) { return m => EvaluateMatch(m, timeSpan); } private string EvaluateMatch(Match match, TimeSpan timeSpan) { switch (match.Value) { case "dd": return timeSpan.Days.ToString("00"); case "d": return timeSpan.Days.ToString("0"); case "hh": return timeSpan.Hours.ToString("00"); case "h": return timeSpan.Hours.ToString("0"); case "mm": return timeSpan.Minutes.ToString("00"); case "m": return timeSpan.Minutes.ToString("0"); case "ss": return timeSpan.Seconds.ToString("00"); case "s": return timeSpan.Seconds.ToString("0"); case "fffffff": return (timeSpan.Milliseconds * 10000).ToString("0000000"); case "ffffff": return (timeSpan.Milliseconds * 1000).ToString("000000"); case "fffff": return (timeSpan.Milliseconds * 100).ToString("00000"); case "ffff": return (timeSpan.Milliseconds * 10).ToString("0000"); case "fff": return (timeSpan.Milliseconds).ToString("000"); case "ff": return (timeSpan.Milliseconds / 10).ToString("00"); case "f": return (timeSpan.Milliseconds / 100).ToString("0"); default: return match.Value; } } }
Мы еще не закончили. С помощью этого типа вы можете назначить пользовательский форматер для столбца в вашем
DataGridView
, который вы хотите использовать для отображения ваших значенийTimeSpan
.Предположим, что столбец является называется "Время"; тогда вы сделаете это:
DataGridViewColumn timeColumn = dataGridView.Columns["Time"]; timeColumn.DefaultCellStyle.FormatProvider = new TimeSpanFormatter(); timeColumn.DefaultCellStyle.Format = "hh:mm";
Итак, теперь ты готов, верно?
Ну, по какой-то странной причине, вы все еще не на 100% там. Почему пользовательское форматирование не может сработать в этот момент, я честно не могу вам сказать. Но мы почти закончили. Последний шаг-обработать событиеCellFormatting
, чтобы эта новая функциональность, которую мы написали, действительно вступила в силу:Наконец-то мы закончили. Установка свойстваprivate void dataGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) { var formatter = e.CellStyle.FormatProvider as ICustomFormatter; if (formatter != null) { e.Value = formatter.Format(e.CellStyle.Format, e.Value, e.CellStyle.FormatProvider); e.FormattingApplied = true; } }
DefaultCellStyle.Format
объектаDataGridViewColumn
, который вы хотите форматирование в соответствии с вашими пользовательскими правилами теперь должно работать, как и ожидалось.*Итак, "h"/"hh"для часов,"m" / " mm " для минут. и т.д.
Можно добиться того же эффекта, просто используя событие CellFormatting.
Это, очевидно, не такое всеобъемлющее решение, но довольно быстрое.private void dataGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) { if (e.Value != null && e.Value != DBNull.Value) e.Value = ((TimeSpan)e.Value).Hours.ToString("00") + ":" + ((TimeSpan)e.Value).Minutes.ToString("00"); }
Попробуйте выполнить следующий код
dataGridView1.Columns["columnName"].DefaultCellStyle.Format = "hh\\:mm";