{"record":{"id":"e167e05d861a5d4c","repo":"stride3d/stride","slug":"convertback-is-not-supported-by-this-ivalueconverter","errorCode":null,"errorMessage":"ConvertBack is not supported by this IValueConverter.","messagePattern":"ConvertBack is not supported by this IValueConverter\\.","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"sources/presentation/Stride.Core.Translation.Presentation/ValueConverters/LocalizableConverter.cs","lineNumber":35,"sourceCode":"    public abstract class LocalizableConverter<TConverter> : MarkupExtension, IValueConverter\n        where TConverter : LocalizableConverter<TConverter>, new()\n    {\n        // Keep a cache per assembly (since localization is grouped per assembly)\n        private static readonly Dictionary<Assembly, LocalizableConverter<TConverter>> Cache = new Dictionary<Assembly, LocalizableConverter<TConverter>>();\n\n        /// <summary>\n        /// The assembly to lookup the translation.\n        /// </summary>\n        protected Assembly Assembly { get; private set; }\n\n        /// <inheritdoc />\n        public abstract object Convert(object value, Type targetType, object parameter, CultureInfo culture);\n\n        /// <inheritdoc />\n        public virtual object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)\n        {\n            // By default, a localizable converter is one-way only.\n            throw new NotSupportedException($\"ConvertBack is not supported by this {nameof(IValueConverter)}.\");\n        }\n\n        /// <inheritdoc/>\n        public override object ProvideValue(IServiceProvider serviceProvider)\n        {\n            var assembly = MarkupExtensionHelper.RetrieveLocalAssembly(serviceProvider);\n            if (!Cache.TryGetValue(assembly, out var converter))\n            {\n                converter = new TConverter { Assembly = assembly };\n                Cache.Add(assembly, converter);\n            }\n            return converter;\n        }\n    }\n}\n","sourceCodeStart":17,"sourceCodeEnd":51,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/presentation/Stride.Core.Translation.Presentation/ValueConverters/LocalizableConverter.cs#L17-L51","documentation":"LocalizableConverter (base class of the localization value converters in Stride.Core.Translation.Presentation) is one-way by design: it converts raw localized values for display. Its virtual ConvertBack default implementation throws NotSupportedException because reverse-translating a displayed string to its source value has no general solution.","triggerScenarios":"Any binding using a LocalizableConverter-derived converter (e.g. TranslateConverter/PluralizationConverter) with TwoWay or OneWayToSource mode, so the binding engine calls ConvertBack.","commonSituations":"Making a localized label editable; switching binding modes while refactoring; assuming the converter behaves like standard framework converters that support round-trips.","solutions":["Set binding Mode=OneWay explicitly; two-way localization bindings are unsupported.","Override ConvertBack in your own derived converter to return the raw value if your data model stores the same string that is displayed.","Restructure so the ViewModel owns the translatable key and the localized text is presentation-only."],"exampleFix":"// before\nBindingOperations.SetBinding(tb, TextBlock.TextProperty, new Binding(\"Name\") { Converter = new TranslateConverter(), Mode = BindingMode.TwoWay });\n// after\nBindingOperations.SetBinding(tb, TextBlock.TextProperty, new Binding(\"Name\") { Converter = new TranslateConverter(), Mode = BindingMode.OneWay });","handlingStrategy":"validation","validationCode":"var binding = new Binding(\"Name\") { Converter = new TranslateConverter(), Mode = BindingMode.OneWay };","typeGuard":null,"tryCatchPattern":"try { /* binding setup */ }\ncatch (NotSupportedException) when (ex.Message.Contains(\"ConvertBack\")) { /* switch binding to OneWay or override ConvertBack */ }","preventionTips":["Keep LocalizableConverter-derived converters one-way","Override ConvertBack only when displayed string equals stored value","Own localization state in the ViewModel, not the binding"],"tags":["notsupported","binding","localization","oneway"],"backgroundTag":"unsupported-operation","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}