Формат TimeSpan в столбце DataGridView
Я видел эти вопросы но оба включают методы, которые недоступны в значении формата CellStyle. Я хочу показать только часть часов и минут (16:05), а не секунды (16:05:13). Я попытался заставить значение секунд равняться нулю, но все равно получил что-то вроде 16:05:00. Не используя kludge, как предоставление строки или DateTime (и только показывая часть часа / минут), Есть ли способ заставить форматирование делать то, что я хотеть.
5 ответов
я только что обнаружил это сам. К сожалению, решение довольно запутанное. Хорошая новость в том, что это работает.
во-первых, вам нужен ICustomFormatter
реализация, которая имеет дело с TimeSpan
значения. Платформа .NET framework не включает такой тип из коробки; я гадание это потому, что 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% пути туда. Почему пользовательское форматирование не может сработать в этот момент, я честно не мог сказать вам. Но мы ... --15-->почти сделано. Последним шагом является обработка 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");
}
это, очевидно, не столь всеобъемлющее решение, но довольно быстрое.
Я не знаю, как установить формат ячейки, чтобы показывать только часы и минуты. Я бы предложил вам установить формат ячейки в строку и отформатировать значение следующим образом:
String.Format("{0:D2}:{1:D2}",
DateTime.Now.TimeOfDay.Hours, DateTime.Now.TimeOfDay.Minutes);