Формат TimeSpan в столбце DataGridView - PullRequest
7 голосов
/ 02 сентября 2010

Я видел эти вопросы , но оба включают методы, которые недоступны в значении формата CellStyle. Я только хочу показать часть часов и минут (16:05); а не секунды (16:05:13). Я пытался заставить значение секунд до нуля, но все равно получилось что-то вроде 16:05:00. Если не считать использования kludge, такого как предоставление строки или DateTime (и только отображение части часов / минут), есть ли какой-нибудь способ, которым я могу заставить форматирование делать то, что я хочу.

Ответы [ 5 ]

11 голосов
/ 02 сентября 2010

Я только что обнаружил это сам. К сожалению, решение довольно сложное. Хорошая новость в том, что это работает.

Во-первых, вам нужна реализация ICustomFormatter, которая работает со значениями TimeSpan. .NET Framework не включает в себя такой тип "из коробки"; Я предполагаю это потому, что Microsoft не хотела иметь дело с неоднозначностью, связанной с форматированием TimeSpan (например, означает ли "чч" общее количество часов или только компонент часа?) И последовавший натиск проблем с поддержкой, которые могли возникнуть, когда эти неясности смутили разработчиков.

Все в порядке - просто реализуй свое. Ниже приведен пример класса, который я написал, который использует в основном те же строки пользовательского формата, что и 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;
    }
}

Наконец, мы закончили. Установка свойства DefaultCellStyle.Format для DataGridViewColumn, которое вы хотите отформатировать в соответствии с вашими пользовательскими правилами, теперь должна работать как положено.

* Итак, «ч» / «чч» для часов, «м» / «мм» для минут. и т.д.

9 голосов
/ 16 ноября 2012

Этого же эффекта можно добиться, просто используя событие 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");
}

Это, очевидно, не столь всеобъемлющее решение, но довольно быстрое.

4 голосов
/ 19 февраля 2015

Попробуйте следующий код

dataGridView1.Columns["columnName"].DefaultCellStyle.Format = "hh\\:mm";
2 голосов
/ 02 сентября 2010

Я не знаю, как настроить формат ячейки, чтобы показывать только часы и минуты. Я бы посоветовал вам установить формат ячейки в строку и отформатировать значение следующим образом:

String.Format("{0:D2}:{1:D2}",
    DateTime.Now.TimeOfDay.Hours, DateTime.Now.TimeOfDay.Minutes);
0 голосов
/ 09 августа 2017

Использовать строку формата "hh\\:mm". * например 1002 *

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