2010-09-02 14 views
7

Ho visto these ma entrambi implicano metodi che non sono disponibili nel valore di Formato CellStyle. Voglio solo mostrare la porzione di ore e minuti (16:05); non anche i secondi (16:05:13). Ho provato a forzare il valore dei secondi a zero ma ho ancora qualcosa come 16:05:00. A meno di usare un kludge come fornire una stringa o un DateTime (e solo mostrando la parte ore/minuti) c'è un modo in cui posso ottenere la formattazione per fare ciò che voglio.Formato TimeSpan nella colonna DataGridView

risposta

11

ho appena scoperto questo me stesso. Sfortunatamente, la soluzione è abbastanza coinvolta. La buona notizia è che funziona.

In primo luogo, è necessaria un'implementazione ICustomFormatter che si occupa dei valori TimeSpan. Il framework .NET non include questo tipo di out-of-the-box; Sono indovinando questo perché Microsoft non voleva avere a che fare con l'ambiguità implicita nella formattazione di TimeSpan (ad esempio, "hh" significa ore totali o solo la componente dell'ora?) E il conseguente assalto di problemi di supporto che sorgerebbero quando queste ambiguità confondevano gli sviluppatori.

Va bene, basta implementare il proprio. Qui di seguito è una classe di esempio ho scritto che utilizza fondamentalmente the same custom format strings as DateTime (quelli che erano applicabili, in ogni caso) *:

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

Non abbiamo ancora finito. Con questo tipo, è possibile assegnare un formattatore personalizzato alla colonna nel proprio DataGridView che si desidera utilizzare per la visualizzazione dei valori TimeSpan.

Diciamo che la colonna è chiamata "Tempo"; quindi si dovrebbe fare questo:

DataGridViewColumn timeColumn = dataGridView.Columns["Time"]; 
timeColumn.DefaultCellStyle.FormatProvider = new TimeSpanFormatter(); 
timeColumn.DefaultCellStyle.Format = "hh:mm"; 

Quindi ora sei impostato, giusto?

Bene, per qualche strana ragione, non sei ancora al 100% del modo in cui ci sono. Perché la formattazione personalizzata non può dare il via a questo punto, sinceramente non saprei dirtelo. Ma siamo quasi fatto. L'unico passo finale è quello di gestire l'evento CellFormatting per ottenere questa nuova funzionalità che abbiamo scritto a prendere in realtà effetto:

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

Finalmente, abbiamo finito. L'impostazione della proprietà DefaultCellStyle.Format del DataGridViewColumn si desidera formattato in base alle proprie regole personalizzate ora dovrebbe funzionare come previsto.

* Quindi, "h"/"hh" per ore, "m"/"mm" per minuti. ecc.

+0

Si potrebbe avere ragione sul perché non è nel quadro. È molto più impegnato di quanto pensassi sarebbe stato, grazie. –

+0

Funziona perfettamente. Un cuore sentito Grazie. –

+0

Fantastico, grazie amico. Funziona perfettamente. – Sharique

2

Non so come impostare il formato della cella per mostrare solo ore e minuti. Io suggerirei di impostare il formato della cella a stringa e formattare il valore in questo modo:

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

È possibile ottenere l'effetto stesso utilizzando semplicemente l'evento 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"); 
} 

Questa ovviamente non è una soluzione completa, ma piuttosto veloce.

+0

A partire da .NET 4 questo potrebbe essere semplificato per la formattazione diretta: 'if (e.ColumnIndex == idx && e.Value! = Null && e.Value! = DBNull.Value) {e.Value = ((TimeSpan) e.Value) .ToString ("ddd \\. hh \\: mm \\: ss"); } ', o anche meglio, aggiungendo quanto segue all'inizializzazione di DataGridView: ' dgv.Columns [idx] .DefaultCellStyle.Format = "ddd \\. Hh \\: mm \\: ss"; ' – Astrogator

4

provare il seguente codice

dataGridView1.Columns["columnName"].DefaultCellStyle.Format = "hh\\:mm"; 
0

stringa Usa formato "hh\\:mm". , ad esempio

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

Controlla sempre la tua formattazione prima di postare per assicurarti che l'intero punto non sia stato perso da un fraintendimento di Markdown. –

Problemi correlati