{"record":{"id":"8eadc916bb4a1e5f","repo":"dotnet/wpf","slug":"sr-attachedpropertyontypeconvertedorstringproperty","errorCode":null,"errorMessage":"SR.AttachedPropertyOnTypeConvertedOrStringProperty","messagePattern":"SR\\.AttachedPropertyOnTypeConvertedOrStringProperty","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlObjectReader.cs","lineNumber":908,"sourceCode":"                    }\n                    else\n                    {\n                        context.Instance = null;\n                        valueInfo = ObjectMarkupInfo.ForObject(propertyValue, context, propertyConverter);\n                    }\n                }\n\n                return valueInfo;\n            }\n\n            private static void ThrowIfPropertiesAreAttached(object value, XamlMember property, SerializerContext context)\n            {\n                var props = context.Runtime.GetAttachedProperties(value);\n                if (props is not null)\n                {\n                    if (property is not null)\n                    {\n                        throw new InvalidOperationException(SR.Format(SR.AttachedPropertyOnTypeConvertedOrStringProperty, property.Name, value.ToString(), props[0].Key.ToString()));\n                    }\n                    else\n                    {\n                        throw new InvalidOperationException(SR.Format(SR.AttachedPropertyOnDictionaryKey, value.ToString(), props[0].Key.ToString()));\n                    }\n                }\n            }\n\n            // Reproduce the logic of System.ComponentModel.ReflectPropertyDescriptor.ShouldSerializeValue\n            private static bool ShouldWriteProperty(object source, XamlMember property, SerializerContext context)\n            {\n                bool isReadOnly = !context.IsPropertyWriteVisible(property);\n\n                if (!isReadOnly)\n                {\n                    object defaultValue;\n                    if (GetDefaultValue(property, out defaultValue))\n                    {","sourceCodeStart":890,"sourceCodeEnd":926,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlObjectReader.cs#L890-L926","documentation":"When XamlObjectReader converts a property value to a string (via a type converter) it checks whether that value itself exposes attached-property content (GetAttachedProperties). If it does, the XAML output would lose those attached properties, which is unrepresentable in attribute/string form, so an InvalidOperationException names the property, value, and the offending attached property.","triggerScenarios":"Reading an object where property P's value is type-converted or written as a string, and that value has attached properties set (e.g. a string/converted value carrying Canvas.Left, Grid.Row, etc.) — ThrowIfPropertiesAreAttached with property != null (XamlObjectReader.cs:906-908).","commonSituations":"A custom TypeConverter that converts a complex object (with attached properties set on it) to a string; WPF types stored in a property with a converter attached while layout attached properties were applied to them; cloning objects between UI trees during serialization.","solutions":["Remove attached-property setters from values that are serialized through a type converter or as strings, or move them to a container element in XAML.","Change the property's serialization so the value is written as an object element (remove/replace the TypeConverter) so attached properties can be emitted as child elements.","Set the attached properties in the XAML on the parent/other element rather than on the converted value."],"exampleFix":"// before\ncanvas.Children.Add(text); // text has Canvas.Left set and is stored via TypeConverter string property\nxamlText = tc.ConvertToString(text); // throws: attached properties lost\n// after\n// serialize text as an object element instead of a converted string\nCanvas.SetLeft(text, 10); // move attached property usage to the element tree, not a string property","handlingStrategy":"validation","validationCode":"static void EnsureNoAttachedProps(object value) {\n  if (value is DependencyObject d) {\n    foreach (var p in new[]{Canvas.LeftProperty, Canvas.TopProperty, Grid.RowProperty})\n      if (d.ReadLocalValue(p) != DependencyProperty.UnsetValue)\n        throw new InvalidOperationException(\"Attached properties set on a type-converted/string property value.\");\n  }\n}","typeGuard":null,"tryCatchPattern":"try { xaml = reader.ReadSubtree(); /* serialize */ }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"attached\")) { /* move attached properties or change serialization mode */ }","preventionTips":["Do not set attached properties on values that are serialized through TypeConverters.","Prefer serializing such values as object elements, not strings.","Audit custom TypeConverters for complex object inputs."],"tags":["xaml","attached-property","typeconverter"],"backgroundTag":"unsupported-operation","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}