c# - 在 DataGridView 列中格式化 TimeSpan

我见过 these questions但两者都涉及 CellStyle Format 值中不可用的方法。我只想显示小时和分钟部分(16:05);不是秒数(16:05:13)。我尝试将秒值强制为零,但仍然得到类似 16:05:00 的结果。没有使用像提供字符串或 DateTime(并且只显示小时/分钟部分)这样的组合,有什么方法可以让我做我想做的格式化。

最佳答案

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

首先,您需要一个处理 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;
    }
}

终于,我们完成了。设置您希望根据自定义规则格式化的 DataGridViewColumnDefaultCellStyle.Format 属性现在应该可以按预期工作了。

*所以,“h”/“hh”代表小时,“m”/“mm”代表分钟。等等

https://stackoverflow.com/questions/3627922/

相关文章:

java - 将 double 格式设置为分数

html - 在电子邮件正文中应用 HTML 格式

c++ - Qt - QPushButton 文本格式

reporting-services - SSRS 格式显示为百分比

c++ - 是否有一个自动源代码格式化程序可以很好地包装 C/C++ 行?

sql-server - SQL 2008 使用 LTrim(RTrim 并且数据中仍有空格

c# - 从时间中删除前导零以显示耗时

time - ColdFusion - 从分钟数创建时间

java - 更改java控制台输出的颜色

haskell - 如何将 Rational 转换为 "pretty"字符串?