Mam dość nieprecyzyjne wymagania formatowania dla wartości decimal
. W skrócie: wyświetlaj do dwóch miejsc po przecinku z końcowym odstępem, chyba że trzeci dziesiętny to 5, w którym to przypadku wyświetla się do trzech miejsc po przecinku.Poszerzanie niestandardowych możliwości formatowania wbudowanych typów
To formatowanie musi być dość elastyczne. W szczególności tylna przestrzeń nie zawsze będzie pożądana, a "½" może być preferowane, gdy trzeci dziesiętny jest "5".
Przykłady:
- 1,13 będzie wyświetlany jako "01,13" ze spacją lub "01,13" bez niego
- 1,315 będzie wyświetlany jako "01.315" lub "01.31½"
Muszę używać tej logiki w spójny sposób w innych niezwiązanych z nią elementach interfejsu użytkownika. Mam chwilowo napisane go jako konwerter wartości WPF, ale to tylko na pokaz:
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();
}
}
Jestem teraz próbuje wydobyć to w bardziej fundamentalnym bloku budowlanego można używać przez całe warstwy UI. Moją pierwszą myślą było dostawcą formatu niestandardowego, które mogę potem używać z Binding
:
<TextBlock Text="{Binding Value, FormatString=WHATEVER}"/>
Chodzi o to, że ciąg formatu może być coś takiego jak „# 0,005”, która wskazuje tylko pokazać trzeciego miejsca po przecinku, jeśli jest to 5 lub "# 0.00F", który próbuje reprezentować trzeci dziesiętny jako ułamek. Jednak nie byłem w stanie znaleźć sposobu na użycie określonego dostawcy formatu z powiązania, co wydaje mi się poważnym ograniczeniem, ale może brakuje mi czegoś ...?
Po dalszych eksperymentów i dochodzenia, doszedłem do wniosku, że moją jedyną opcją jest, aby zdefiniować własny typ:
public struct Price : IFormattable
Ten typ będzie hermetyzacji dodatkowe możliwości formatowania wymagam. Jednak teraz mam kolejną zagadkę: w mojej implementacji ToString
, jak mogę wykorzystać istniejące możliwości formatowania decimal.ToString(string, IFormatProvider)
bez ingerencji w moje własne? Wygląda na to, że byłoby to dość cholernie brudne i powoduje to, że skłaniam się ku bardziej ograniczonemu rozwiązaniu po prostu definiując "G" (dwa lub trzy miejsca po przecinku, bez spacji) i "S" (to samo co "G", ale z końcową przestrzenią jeśli to konieczne) dla mojej struktury Price
.
Czy ktoś może mi powiedzieć, czy istnieje sposób dla mnie, aby zrobić tego rodzaju niestandardowe możliwości formatowania bez zbytniego wysiłku?
Czy jakiś unikalny prefiks do formatowania pracy ciąg do odróżnić niestandardowe i domyślne formatowanie? Podobnie jak "& # 0,00" dla niestandardowego i "# 0,00" dla domyślnego (jeśli pierwszy znak specjalny - użyj niestandardowego ...) –
@Alexei: działałoby to tylko wtedy, gdybym chciał przejąć pełną własność kodu formatującego, ale wolałbym przekazać to wbudowane formatowanie, a następnie uzupełnić moje własne bity. W przeciwnym razie musiałbym ponownie wdrożyć strasznie dużo wbudowanych funkcji. –
spróbuj tego http://stackoverflow.com/questions/11438089/how-to-delegate-to-default-format-provider – amald