У меня есть некоторые довольно неудобные требования к форматированию для значений decimal
. В двух словах: отображение до двух знаков после запятой с конечным пространством, если третья десятичная цифра не равна 5, и в этом случае отображается три знака после запятой.
Это форматирование также должно быть достаточно гибким. В частности, конечное пространство не всегда будет желательным, а "½" может быть предпочтительным, если третья десятичная цифра равна "5".
Примеры:
- 1.13 будет отображаться как "01.13" с пробелом или "01.13" без него
- 1.315 будет отображаться как "01.315" или "01.31½"
Мне нужно последовательно использовать эту логику для других не связанных между собой частей пользовательского интерфейса. Я временно написал его как конвертер значений WPF, но это просто для демонстрации:
public sealed class PriceConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(value is decimal))
{
return DependencyProperty.UnsetValue;
}
var decimalValue = (decimal)value;
var formattedDecimalValue = decimalValue.ToString("#0.000", CultureInfo.InvariantCulture);
var lastFormattedChar = formattedDecimalValue[formattedDecimalValue.Length - 1];
switch (lastFormattedChar)
{
case '0':
return formattedDecimalValue.Substring(0, formattedDecimalValue.Length - 1) + " ";
case '5':
return formattedDecimalValue.Substring(0, formattedDecimalValue.Length - 1) + "½";
default:
return formattedDecimalValue;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Теперь я пытаюсь извлечь это в более фундаментальный строительный блок, который я могу использовать во всем слое пользовательского интерфейса. Моя первоначальная мысль была поставщиком произвольного формата, который я мог бы использовать с Binding
:
<TextBlock Text="{Binding Value, FormatString=WHATEVER}"/>
Идея заключается в том, что строка формата может быть чем-то вроде "# 0.005", что указывает только на отображение третьего десятичного знака, если оно равно 5 или "# 0.00F", которое пытается представить третью десятичную дробь в виде дроби. Однако мне не удалось найти способ использования определенного поставщика форматов из привязки, который кажется для меня основным ограничением, но, возможно, мне что-то не хватает...?
После дополнительных экспериментов и исследований я пришел к выводу, что мой единственный вариант - определить мой собственный тип:
public struct Price : IFormattable
Этот тип будет инкапсулировать дополнительные возможности форматирования, которые мне нужны. Однако теперь у меня есть еще одна загадка: в моей реализации ToString
, как я могу использовать существующие возможности форматирования decimal.ToString(string, IFormatProvider)
, не вмешиваясь в мои собственные? Похоже, что это было бы довольно грязно, и это заставило меня склониться к более ограниченному решению только определения "G" (два или три десятичных знака, без конечного пространства) и "S" (то же, что и "G", но с конечным пространством, если необходимо) форматов для моей структуры Price
.
Может ли кто-нибудь сказать мне, есть ли способ для меня сделать такую возможность форматирования без лишних хлопот?