Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I just discovered this myself. Unfortunately, the solution is pretty involved. The good news is that it works.</p> <p>Firstly, you need an <code>ICustomFormatter</code> implementation that deals with <code>TimeSpan</code> values. The .NET framework does not include such a type out-of-the-box; I am <em>guessing</em> this is because Microsoft didn't want to have to deal with the ambiguity involved in formatting a <code>TimeSpan</code> (e.g., does "hh" mean total hours or only the hour component?) and the ensuing onslaught of support issues that would arise when these ambiguities confused developers.</p> <p>That's OK -- just implement your own. Below is a sample class I wrote that uses basically <a href="http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx" rel="noreferrer">the same custom format strings as <code>DateTime</code></a> (those that were applicable, anyway)*:</p> <pre><code>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 =&gt; 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; } } } </code></pre> <p>We're not finished yet. With this type in place, you are equipped to assign a custom formatter to the column in your <code>DataGridView</code> that you want to use for displaying your <code>TimeSpan</code> values.</p> <p>Let's say that column is called "Time"; then you would do this:</p> <pre><code>DataGridViewColumn timeColumn = dataGridView.Columns["Time"]; timeColumn.DefaultCellStyle.FormatProvider = new TimeSpanFormatter(); timeColumn.DefaultCellStyle.Format = "hh:mm"; </code></pre> <p>So now you're set up, right?</p> <p>Well, for some odd reason, you're still not 100% of the way there. Why custom formatting can't kick in at this point, I honestly couldn't tell you. But we're <em>almost</em> done. The one final step is to handle the <code>CellFormatting</code> event to get this new functionality we've written to actually take effect:</p> <pre><code>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; } } </code></pre> <p>At last, we're finished. Setting the <code>DefaultCellStyle.Format</code> property of the <code>DataGridViewColumn</code> you want formatted according to your custom rules should now work as expected.</p> <p><sub>*So, "h"/"hh" for hours, "m"/"mm" for minutes. etc.</sub></p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload