这是我自己发现的。不幸的是,解决方案非常复杂。好消息是它有效。
首先,您需要一个处理TimeSpan 值的ICustomFormatter 实现。 .NET 框架不包括这种开箱即用的类型;我猜测这是因为 Microsoft 不想处理格式化 TimeSpan 所涉及的歧义(例如,“hh”是指总小时数还是仅表示小时数部分?)和当这些歧义使开发人员感到困惑时,会出现大量支持问题。
没关系 - 只需实现您自己的即可。下面是我编写的一个示例类,它基本上使用the same custom format strings as 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;
}
}
终于,我们完成了。设置您希望根据自定义规则格式化的DataGridViewColumn 的DefaultCellStyle.Format 属性现在应该可以按预期工作了。
*所以,“h”/“hh”代表小时,“m”/“mm”代表分钟。等等