在DataGridView列中格式化TimeSpan

我见过这些 问题,但都涉及CellStyle Format值中没有的方法。 我只想显示小时和分钟部分(16:05); 不是秒(16:05:13)。 我试图强制秒值为零,但仍然像16:05:00。 如果没有使用像提供字符串或DateTime(并且仅显示小时/分钟部分)的kludge,那么我可以通过任何方式获得格式化以完成我想要的操作。

我自己就是发现了这个。 不幸的是,解决方案非常复杂。 好消息是它有效。

首先,您需要一个处理TimeSpan值的ICustomFormatter实现。 .NET框架不包含这种开箱即用的类型; 我这是因为微软不想处理格式化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事件以获得我们编写的实际生效的新function:

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

最后,我们完成了。 根据自定义规则设置要格式化的DataGridViewColumnDefaultCellStyle.Format属性现在应该按预期工作。

*所以,“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"; 

我不知道如何设置单元格的格式只显示小时和分钟。 我建议您将单元格的格式设置为字符串,并将值格式化为:

 String.Format("{0:D2}:{1:D2}", DateTime.Now.TimeOfDay.Hours, DateTime.Now.TimeOfDay.Minutes); 

使用格式字符串"hh\\:mm" 。 例如

 YourGrid.Column[index].DefaultCellStyle.Format = "hh\\:mm"