{"record":{"id":"f40f58f6887ab7ab","repo":"AvaloniaUI/Avalonia","slug":"if-one-coordinate-is-relative-both-must-be","errorCode":null,"errorMessage":"If one coordinate is relative, both must be.","messagePattern":"If one coordinate is relative, both must be\\.","errorType":"exception","errorClass":"FormatException","httpStatus":null,"severity":"error","filePath":"src/Avalonia.Base/RelativePoint.cs","lineNumber":184,"sourceCode":"        /// Parses a <see cref=\"RelativePoint\"/> string.\n        /// </summary>\n        /// <param name=\"s\">The string.</param>\n        /// <returns>The parsed <see cref=\"RelativePoint\"/>.</returns>\n        public static RelativePoint Parse(string s)\n        {\n            using (var tokenizer = new SpanStringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: \"Invalid RelativePoint.\"))\n            {\n                var x = tokenizer.ReadString();\n                var y = tokenizer.ReadString();\n\n                var unit = RelativeUnit.Absolute;\n                var scale = 1.0;\n\n                if (x.EndsWith('%'))\n                {\n                    if (!y.EndsWith('%'))\n                    {\n                        throw new FormatException(\"If one coordinate is relative, both must be.\");\n                    }\n\n                    x = x.TrimEnd('%');\n                    y = y.TrimEnd('%');\n                    unit = RelativeUnit.Relative;\n                    scale = 0.01;\n                }\n\n                return new RelativePoint(\n                    double.Parse(x, CultureInfo.InvariantCulture) * scale,\n                    double.Parse(y, CultureInfo.InvariantCulture) * scale,\n                    unit);\n            }\n        }\n\n        /// <summary>\n        /// Returns a String representing this RelativePoint instance.\n        /// </summary>","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/AvaloniaUI/Avalonia/blob/11c542726898ae954a1ef668c65ec79ec92ab17d/src/Avalonia.Base/RelativePoint.cs#L166-L202","documentation":"Thrown by RelativePoint.Parse when exactly one of the X/Y coordinates is specified with a '%' suffix. A RelativePoint is either fully absolute (pixels) or fully relative (0..1 after scaling), so a mixed form like '50%, 100' is ambiguous and rejected as a FormatException.","triggerScenarios":"Parsing a string such as \"50%, 100\" or \"100, 50%\" via RelativePoint.Parse (commonly from XAML attribute or style markup). The '%' triggers the relative branch, but the other token lacks '%'.","commonSituations":"Hand-written XAML/style string with a typo on one coordinate; a binding or converter that appends '%' to only one value; localized input where one unit got stripped.","solutions":["Make both coordinates the same unit: either \"50%,50%\" or \"50,100\".","If only one dimension should be relative, use an explicit layout (Grid/Column definitions) rather than a mixed RelativePoint string.","Validate the input string has matching '%' suffixes before parsing."],"exampleFix":"<!-- before -->\n<VisualBrush DestinationRect=\"50%, 100\" />\n<!-- after -->\n<VisualBrush DestinationRect=\"50%,50%\" />","handlingStrategy":"validation","validationCode":"if (HasMismatchedPercentSuffix(s)) throw new FormatException(\"Coordinates must both be absolute or both relative (%).\");\nRelativePoint.Parse(s);\n\nstatic bool HasMismatchedPercentSuffix(string s)\n{\n    var parts = s.Split(',', StringSplitOptions.TrimEntries);\n    if (parts.Length != 2) return false;\n    return parts[0].EndsWith('%') ^ parts[1].EndsWith('%');\n}","typeGuard":null,"tryCatchPattern":"try { return RelativePoint.Parse(s); }\ncatch (FormatException) { /* log/markup error */ throw; }","preventionTips":["Author RelativePoint XAML strings with matching units on both coordinates.","Validate XAML markup strings at design time / in tests.","Run converters that append '%' on both components."],"tags":["xaml","parsing","relativepoint","format-exception","markup"],"backgroundTag":null,"analyzedSha":"11c542726898ae954a1ef668c65ec79ec92ab17d","analyzedAt":"2026-08-13T11:57:40.261Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}