Does StringFormat in TextBox make sense?
If I have a TextBox like this:
<TextBox Text="{Binding Voltage, StringFormat={}{0} kV}" />
and the property Voltage, for example. 50, I get "50kV" in my TextBox. This is what I intended.
But now, if the user wants to enter a new value, say 40, and types in "40 kV", he gets a red border because there is a FormatException returning a value.
System.Windows.Data Error: 7 : ConvertBack cannot convert value '40 kV' (type 'String'). BindingExpression:Path=Voltage; DataItem='VMO_VoltageDefinition' (HashCode=19837180); target element is 'TextBox' (Name=''); target property is 'Text' (type 'String') FormatException:'System.FormatException: Die Eingabezeichenfolge hat das falsche Format.
I don't think the users of my program will accept this.
So am I doing something wrong or is this function just not being used in a reasonable way with the TextBox?
StringFormat
is a Binding
markup extension property and in theory can be used in any binding. However, it mostly only makes sense with one-way connections.
You are correct that stringformat doesn't make much sense in a TextBox.
You can work around this with a converter as David suggested, but I recommend that you map the device to a TextBlock outside of the TextBox:
<DockPanel>
<TextBlock Text="kV" DockPanel.Dock="Right />
<TextBox Text="{Binding Voltage}" />
</DockPanel>
It feels more natural and gives a much better user experience.
Alternatively, you can create your own TextBox-derived control with a new Unit or Description property or any other way and modify the holding control to display the device. Then the final markup might look like this:
<my:TextBox Text="{Binding Voltage}" Description="kV" />
I suggest using a converter:
<TextBox Text="{Binding Voltage, Converter={StaticResource VoltageToString}}" />
Where:
<Window.Resources>
<mstf:VoltageToStringx:Key="VoltageToString" />
</Window.Resources>
And the codebehind:
public class VoltageToString: IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
return ((int)value).ToString() + " kV";
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
return int.Parse((string).Replace(" kV",""));
}
}
This is just a basic example, but you have to figure out how to make it more complex.