2010-09-02 24 views
7

he visto thesequestions pero ambos implican métodos que no están disponibles en el valor CellStyle Formato. Solo quiero mostrar la porción de horas y minutos (16:05); no los segundos también (16:05:13). Intenté forzar el valor de los segundos a cero, pero todavía obtuve algo así como 16:05:00. Además de usar un kludge como proporcionar una cadena o un DateTime (y solo se muestra la parte de la hora/minutos), hay alguna forma de que pueda obtener el formato para hacer lo que quiero.Formato TimeSpan en la columna DataGridView

Respuesta

11

Acabo de descubrir esto por mi cuenta. Desafortunadamente, la solución es bastante complicada. La buena noticia es que funciona.

En primer lugar, se necesita una implementación ICustomFormatter que se ocupa de TimeSpan valores. El .NET Framework no incluye un tipo de este tipo fuera de la caja; Estoy adivinando esto se debe a que Microsoft no quiere tener que lidiar con la ambigüedad que participan en el formateo de una TimeSpan (por ejemplo, significa "hh" significará el total de horas o sólo el componente de hora?) Y la subsiguiente avalancha de problemas de soporte que surgiría cuando estas ambigüedades confundieran a los desarrolladores.

Eso está bien, solo implemente el suyo. A continuación se muestra una clase de muestra escribí que utiliza básicamente the same custom format strings as DateTime (los que fuera aplicable, de todos modos) *:

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

No hemos terminado todavía. Con este tipo en su lugar, está equipado para asignar un formateador personalizado a la columna en su DataGridView que desea utilizar para mostrar sus valores TimeSpan.

Digamos que la columna se llama "Time"; entonces usted haría esto:

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

Así que ahora está configurado, ¿verdad?

Bueno, por alguna extraña razón, todavía no estás 100% de la manera allí. Por qué el formato personalizado no puede funcionar en este punto, honestamente no podría decírtelo. Pero estamos casi hecho. El último paso es uno para controlar el evento CellFormatting para obtener esta nueva funcionalidad que hemos escrito para realmente entrar en vigor:

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

Por fin, hemos terminado. Establecer la propiedad DefaultCellStyle.Format del DataGridViewColumn que desea formatear de acuerdo con sus reglas personalizadas ahora debería funcionar como se esperaba.

* Entonces, "h"/"hh" durante horas, "m"/"mm" durante minutos. etc.

+0

Puede tener razón acerca de por qué no está en el marco. Eso es mucho más complicado de lo que pensé que hubiera sido, gracias. –

+0

Funciona a la perfección. Un corazón sentido Gracias. –

+0

Impresionante, gracias amigo. Funciona perfectamente – Sharique

2

No sé cómo configurar el formato de la celda para mostrar sólo las horas y minutos. Sugeriría que establezca el formato de la celda en la cadena y formatee el valor de esta manera:

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

Es posible lograr el efecto mismo sólo por el uso del 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"); 
} 

Evidentemente, esta solución no es tan completa, pero es bastante rápida.

+0

Comenzando con .NET 4 esto podría simplificarse al formateo directamente: 'if (e.ColumnIndex == idx && e.Value! = Null && e.Value! = DBNull.Value) {e.Value = ((TimeSpan)) e.Value) .ToString ("ddd \\. hh \\: mm \\: ss"); } ', o mejor aún, agregando lo siguiente a la inicialización de DataGridView: ' dgv.Columns [idx] .DefaultCellStyle.Format = "ddd \\. Hh \\: mm \\: ss"; ' – Astrogator

4

Prueba el siguiente código

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

Uso formato de cadena "hh\\:mm". por ejemplo

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

Siempre revise su formato antes de publicar para asegurarse de que no se pierda todo el punto por un malentendido de Markdown. –

Cuestiones relacionadas