{"record":{"id":"00f1fcf40c8c222d","repo":"AvaloniaUI/Avalonia","slug":"attached-property-name-expected-after","errorCode":null,"errorMessage":"Attached Property name expected after '.'.","messagePattern":"Attached Property name expected after '\\.'\\.","errorType":"validation","errorClass":"ExpressionParseException","httpStatus":null,"severity":"error","filePath":"src/Avalonia.Base/Data/Core/Parsers/BindingExpressionGrammar.cs","lineNumber":238,"sourceCode":"        {\n            var (ns, owner) = ParseTypeName(ref r);\n\n            if(!r.End && r.TakeIf(')'))\n            {\n                nodes.Add(new TypeCastNode() { Namespace = ns, TypeName = owner });\n                return State.AfterMember;\n            }\n\n            if (r.End || !r.TakeIf('.'))\n            {\n                throw new ExpressionParseException(r.Position, \"Invalid attached property name.\");\n            }\n\n            var name = r.ParseIdentifier();\n\n            if (name.Length == 0)\n            {\n                throw new ExpressionParseException(r.Position, \"Attached Property name expected after '.'.\");\n            }\n\n            if (r.End || !r.TakeIf(')'))\n            {\n                throw new ExpressionParseException(r.Position, \"Expected ')'.\");\n            }\n\n            nodes.Add(new AttachedPropertyNameNode\n            {\n                AcceptsNull = acceptsNull,\n                Namespace = ns,\n                TypeName = owner,\n                PropertyName = name.ToString()\n            });\n            return State.AfterMember;\n        }\n\n        private static State ParseIndexer(ref CharacterReader r, List<INode> nodes)","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/AvaloniaUI/Avalonia/blob/11c542726898ae954a1ef668c65ec79ec92ab17d/src/Avalonia.Base/Data/Core/Parsers/BindingExpressionGrammar.cs#L220-L256","documentation":"Thrown by ParseAttachedProperty after the parser successfully consumed the '.' separator following the type name in '(Owner.', but ParseIdentifier returned an empty span — meaning no valid identifier characters follow the dot. In Avalonia's binding grammar the '.' in an attached property must be immediately followed by a property name; whitespace, end-of-string, or non-identifier characters after the dot all trigger this error.","triggerScenarios":"Writing '(Grid.' at end of string or '(Grid. ' with whitespace or a non-identifier character after the dot. ParseIdentifier only accepts characters valid in a C# identifier, so '(Grid.123)' or '(Grid.;)' would also reach this point after the dot is consumed.","commonSituations":"Typo where the property name was truncated after the dot; auto-complete inserted the dot but not the name; attempting to use a numeric or symbolic property name that is not a valid identifier in the binding mini-language.","solutions":["Add a valid property name immediately after the '.' in the attached-property path: '(Grid.Row)' not '(Grid.)'.","Ensure there is no whitespace between the '.' and the property name.","If the property name contains special characters, use the CLR property name as registered, not the XAML attribute name."],"exampleFix":"<!-- before: no property name after '.' -->\n<TextBox Text=\"{Binding (Grid.)}\" />\n\n<!-- after: property name added -->\n<TextBox Text=\"{Binding (Grid.Row)}\" />","handlingStrategy":"validation","validationCode":"// Check that every '.' inside parentheses is followed by an identifier\nstatic void ValidateAttachedPropertyName(string path)\n{\n    int depth = 0;\n    for (int i = 0; i < path.Length; i++)\n    {\n        if (path[i] == '(') depth++;\n        else if (path[i] == ')') depth--;\n        else if (depth > 0 && path[i] == '.')\n        {\n            if (i + 1 >= path.Length || !(char.IsLetter(path[i + 1]) || path[i + 1] == '_'))\n                throw new ArgumentException(\n                    $\"'.' at position {i} is not followed by a valid property name\");\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    var binding = new Binding(path);\n}\ncatch (ExpressionParseException ex) when (ex.Message.Contains(\"Attached Property name expected\"))\n{\n    logger.LogError($\"Missing property name after '.' at column {ex.Column}\");\n}","preventionTips":["Always complete the '(Type.PropertyName)' pattern in one typing pass to avoid leaving a dangling dot.","If using auto-complete, verify the full expression is inserted, not just the type name and dot.","Test attached-property binding paths with small unit tests against the parser."],"tags":["avalonia","binding","xaml","binding-expression","attached-property","parser","syntax-error"],"backgroundTag":null,"analyzedSha":"11c542726898ae954a1ef668c65ec79ec92ab17d","analyzedAt":"2026-08-13T11:57:40.261Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}