WPF Advanced Format Converter






4.88/5 (11 votes)
Format converter to handle more cases than the StringFormat, including infinity, and NaN
Introduction
The string format capabilities built into Visual Studio is somewhat limited; what if you want to actually display an infinity symbol instead of the word Infinity. It is not possible with the current string format (StringFormat
class
) capability.
Background
I wanted to handle formatting the case of when a double
value was equal to double.NaN
. Would have liked to have just extended the StringFormat
class
, but that class
is sealed
: The limitations within WPF strikes again. Was hoping maybe be able to use a MarkupExtension
, but that did not seem practical. Ended up using my standard backup, the IValueConverter
.
Using the Code
I only implemented the case for double, but obviously
could add the case for float
also. To make the converter work in the Binding
, the Path
is the path to a double value, the converter is this converter (inherited from MarkupExtension
so did not have to previously define the converter), and the format string
is passed in the ConverterParameter
:
<TextBlock Grid.Row="1"
Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="{Binding Positive,
Converter={local:FormatConverter},
ConverterParameter=+0.0;(-0.0);—;+∞;-∞;§}" />
The code handles the following cases:
- Where there are two or less ";", (cases for positive, negative, and zero) then just uses the original format string.
- In the case of 3 ";", then the last format is used for any infinity or NaN values.
- In the case of 4 ";", then the 4th format is used for the two infinity cases, and the last format for the NaN case.
- In the case of 5 ";", then the 4th format is used for positive infinity, the fifth of negative infininty, and the last for NaN.
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is double)
{
var doubleValue = (double)value;
var formats = parameter.ToString().Split(';');
if (formats.Length < 4) return doubleValue.ToString(formats.ToString());
if (formats.Length == 4)
return (double.IsInfinity(doubleValue) || double.IsNaN(doubleValue))
? formats[3]
: doubleValue.ToString(string.Join(";", formats.Take(3).ToArray()));
if (formats.Length == 5)
return double.IsInfinity(doubleValue)
? formats[3]
: double.IsNaN(doubleValue)
? formats[4]
: doubleValue.ToString(string.Join(";", formats.Take(3).ToArray()));
else
return double.IsPositiveInfinity(doubleValue)
? formats[3]
: double.IsNegativeInfinity(doubleValue)
? formats[4]
: double.IsNaN(doubleValue)
? formats[5]
: doubleValue.ToString(string.Join(";", formats.Take(3).ToArray()));
}
if (value is string) return value; //this stop's design time error
throw new NotImplementedException($"Format for {targetType.Name} not implemented");
}
I added the string
case so that there would not be an issue when in design view.
The Sample
I basically used the XAML code above for each of the cases to create the sample. The control to the right has no special formatting, the control to the left used the FormatConverter
with a ConverterParameter
of "+0.0;(-0.0);—;+∞;-∞;§"
History
- 16/06/22: Initial version