AvaloniaUI/Avalonia · error · NotSupportedException
Two way bindings are not supported with a string format
Error message
Two way bindings are not supported with a string format
What it means
StringFormatValueConverter applies a display format (string.Format) to a value flowing source-to-target. It is inherently one-directional: there is no reliable way to reverse-parse a formatted string back into the original source value, so ConvertBack unconditionally throws NotSupportedException. The library throws it to fail fast rather than silently produce wrong data on the source side.
Source
Thrown at src/Avalonia.Base/Data/Converters/StringFormatValueConverter.cs:49
/// </summary>
public string Format { get; }
/// <inheritdoc/>
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
value = Inner?.Convert(value, targetType, parameter, culture) ?? value;
var format = Format!;
if (!format.Contains('{'))
{
format = $"{{0:{format}}}";
}
return string.Format(culture, format, value);
}
/// <inheritdoc/>
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotSupportedException("Two way bindings are not supported with a string format");
}
}
}
View on GitHub (pinned to 11c5427268)
Solutions
- Set the binding Mode to OneWay (or OneTime) so ConvertBack is never invoked.
- Remove StringFormat and instead expose a pre-formatted string property on the viewmodel, or format in the target's own display logic.
- Keep TwoWay but drop the StringFormat and apply formatting through a custom IValueConverter that implements a real ConvertBack parse step.
Example fix
// before
<TextBox Text="{Binding Amount, StringFormat=C, Mode=TwoWay}" />
// after - OneWay display cannot edit; for editable, drop the format
<TextBox Text="{Binding Amount, Mode=TwoWay}" />
<TextBlock Text="{Binding Amount, StringFormat=C}" /> Defensive patterns
Strategy: validation
Validate before calling
// Validate before applying: StringFormat is only valid on one-way display bindings.
Binding ValidateStringFormat(Binding b)
{
if (!string.IsNullOrEmpty(b.StringFormat) &&
(b.Mode == BindingMode.TwoWay || b.Mode == BindingMode.OneWayToSource))
{
throw new InvalidOperationException(
"StringFormat cannot be used with TwoWay/OneWayToSource bindings.");
}
// Mode.Default may resolve to TwoWay for some targets (e.g. TextBox.Text);
// force OneWay when a format is present unless you are sure.
if (!string.IsNullOrEmpty(b.StringFormat) && b.Mode == BindingMode.Default)
b.Mode = BindingMode.OneWay;
return b;
} Try / catch
// ConvertBack is on the hot path; prefer the validation above. If you wrap converters:
try { var back = converter.ConvertBack(v, t, p, c); }
catch (NotSupportedException) { /* StringFormat/one-way converter: ignore write-back */ } Prevention
- Treat StringFormat as display-only: pair it with OneWay/OneTime bindings.
- Remember TextBox.Text, Selector.SelectedItem, and similar default to TwoWay.
- Format on a separate display TextBlock instead of the editable control.
When it happens
Trigger: A binding with BindingMode.TwoWay or BindingMode.OneWayToSource whose Binding/StringFormatValueConverter also has a non-null StringFormat. The mode default for some targets (e.g. TextBox.Text) is TwoWay, so simply adding a StringFormat to such a binding triggers it even when Mode is left unset.
Common situations: Adding StringFormat='C' or StringFormat='N2' to a TwoWay TextBox.Text binding to pretty-print currency/numbers; enabling StringFormat on a TwoWay Slider.Value or ComboBox.SelectedItem binding; upgrading a OneWay binding to TwoWay without removing the format.
Related errors
- Binding mode cannot be Default.
- UpdateSourceTrigger cannot be Default.
- Property {Name} doesn't have a getter
- Property {Name} doesn't have a setter
- DataContextNode is invalid in conjunction with a binding sou
AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13).
Data as JSON: /api/errors/49f1f134535fdaad.
Report an issue: GitHub.