2010-09-02 6 views
7

J'ai vu thesequestions mais les deux impliquent des méthodes qui ne sont pas disponibles dans la valeur Format CellStyle. Je veux seulement montrer la partie heures et minutes (16:05); pas les secondes aussi (16:05:13). J'ai essayé de forcer la valeur des secondes à zéro mais j'ai quand même obtenu quelque chose comme 16:05:00. À moins d'utiliser un kludge comme fournir une chaîne ou un DateTime (et montrer seulement la partie heure/minutes) est-il possible d'obtenir le formatage pour faire ce que je veux.Format TimeSpan dans la colonne DataGridView

Répondre

11

Je viens de découvrir moi-même. Malheureusement, la solution est assez impliquée. Les bonnes nouvelles sont que cela fonctionne.

Premièrement, vous avez besoin d'une implémentation ICustomFormatter qui traite des valeurs TimeSpan. Le framework .NET n'inclut pas un tel type d'out-of-the-box; Je suis devinant c'est parce que Microsoft ne voulait pas avoir à faire face à l'ambiguïté impliquée dans le formatage TimeSpan (par exemple, «hh» signifie heures totales ou seulement le composant heure?) Et l'assaut subséquente de problèmes de support que se poserait lorsque ces ambiguïtés ont confondu les développeurs.

C'est OK - il suffit d'implémenter le vôtre. Voici une classe exemple, j'ai écrit qui utilise essentiellement the same custom format strings as DateTime (ceux qui étaient applicables, de toute façon) *:

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

Nous ne sommes pas encore fini. Avec ce type en place, vous êtes équipé pour affecter un formateur personnalisé à la colonne de votre DataGridView que vous souhaitez utiliser pour afficher vos valeurs TimeSpan.

Disons que cette colonne est appelée "Time"; alors vous feriez ceci:

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

Alors maintenant vous êtes configuré, non?

Eh bien, pour une raison étrange, vous n'êtes toujours pas à 100% du chemin. Pourquoi la mise en forme personnalisée ne peut pas démarrer à ce stade, honnêtement, je ne pouvais pas vous le dire. Mais nous sommes presque fait. Une étape finale consiste à gérer l'événement CellFormatting pour obtenir cette nouvelle fonctionnalité que nous avons écrit à prendre effectivement effet:

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

Enfin, nous aurons terminé. Définir la propriété DefaultCellStyle.Format de la DataGridViewColumn que vous voulez formaté en fonction de vos règles personnalisées doit maintenant fonctionner comme prévu.

* Donc, "h"/"hh" pour les heures, "m"/"mm" pour les minutes.

+0

Vous avez peut-être raison de dire pourquoi ce n'est pas dans le cadre. C'est beaucoup plus impliqué que je ne le pensais, merci. –

+0

Fonctionne parfaitement. Un coeur senti Merci. –

+0

Génial, Merci mon pote. Cela fonctionne parfaitement. – Sharique

2

Je ne sais pas comment définir le format de la cellule pour afficher uniquement les heures et les minutes. Je vous suggère de définir le format de la cellule à chaîne et formater la valeur comme ceci:

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

Il est possible de réaliser l'effet même en utilisant simplement l'événement 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"); 
} 

Ceci n'est évidemment pas une solution aussi complète, mais assez rapide.

+0

A partir de .NET 4, ceci pourrait être simplifié pour formater directement: 'if (e.ColumnIndex == idx && e.Value! = Null && e.Value! = DBNull.Value) {e.Value = ((TimeSpan) e.Value) .ToString ("ddd \\. hh \\: mm \\: ss"); } ', ou encore mieux, en ajoutant ce qui suit à l'initialisation de DataGridView: ' dgv.Columns [idx] .DefaultCellStyle.Format = "ddd \\. Hh \\: mm \\: ss"; ' – Astrogator

4

Essayez le code suivant

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

chaîne de format Utilisez "hh\\:mm". par exemple

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

Vérifiez toujours votre mise en forme avant de poster pour vous assurer que le point entier n'a pas été perdu en raison d'une mauvaise compréhension de Markdown. –

Questions connexes