{"record":{"id":"95fe8d1648766f6f","repo":"dotnet/wpf","slug":"inverse-sr-visual-notadescendant-sr-visual-notanancestor","errorCode":null,"errorMessage":"inverse ? SR.Visual_NotADescendant : SR.Visual_NotAnAncestor","messagePattern":"inverse \\? SR\\.Visual_NotADescendant : SR\\.Visual_NotAnAncestor","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Visual.cs","lineNumber":4573,"sourceCode":"                    if (embedded2Don3D)\n                    {\n                        visualForGenTransform = gAsVisual3D.Visual;\n                    }\n                    else\n                    {\n                        visualForGenTransform = this;\n                        embedded2Don3D = true;\n                    }\n\n                    group.Children.Add(new GeneralTransform2DTo3DTo2D(gAsVisual3D, visualForGenTransform));\n\n                    g = VisualTreeHelper.GetContainingVisual2D(gAsVisual3D);\n                }\n            }\n\n            if (g != ancestor)\n            {\n                throw new System.InvalidOperationException(inverse ? SR.Visual_NotADescendant : SR.Visual_NotAnAncestor);\n            }\n\n            // At this point, we will have 0 or more transforms in the GeneralTransformGroup\n            // and the matrix which, if not identity, should be appended to the GeneralTransformGroup.\n            // If, as is commonly the case, this loop terminates without encountering a bitmap effect\n            // we will simply use the Matrix.\n\n            // Assert that a non-null group implies at least one child\n            Debug.Assert((group == null) || (group.Children.Count > 0));\n\n            // Do we have a group?\n            if (group != null)\n            {\n                if (!m.IsIdentity)\n                {\n                    group.Children.Add(new MatrixTransform(m));\n                }\n","sourceCodeStart":4555,"sourceCodeEnd":4591,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Visual.cs#L4555-L4591","documentation":"Visual.TryTransformToAncestor/ancestor transform helpers throw InvalidOperationException with SR.Visual_NotAnAncestor (or Visual_NotADescendant when inverse) when, after walking the visual/visual3D ancestry, the target does not stand in the required ancestor/descendant relation.","triggerScenarios":"Calling TransformToAncestor(a) where a is not an ancestor of this visual, or TransformToDescendant(d) where d is not a descendant; 2D/3D boundary cases where GetContainingVisual2D does not reach the given ancestor.","commonSituations":"Passing a sibling instead of an ancestor; element moved/re-parented between computing and transforming; mixing Viewport2DVisual3D content with ordinary 2D ancestry assumptions.","solutions":["Verify the relationship first (walk VisualTreeHelper.GetParent chain up to the target)","Recompute the transform after any layout/re-parenting changes","For 2D-in-3D content, use the containing Viewport2DVisual3D as the ancestor"],"exampleFix":"// before\nvar t = child.TransformToAncestor(sibling);\n// after\nbool isAncestor = false;\nfor (DependencyObject p = VisualTreeHelper.GetParent(child); p != null; p = VisualTreeHelper.GetParent(p))\n    if (p == sibling) { isAncestor = true; break; }\nif (isAncestor) { var t = child.TransformToAncestor(sibling); }","handlingStrategy":"validation","validationCode":"bool IsAncestor(DependencyObject ancestor, DependencyObject node) { for (DependencyObject p = node; p != null; p = VisualTreeHelper.GetParent(p)) if (p == ancestor) return true; return false; }","typeGuard":"bool IsAncestorOf(Visual a, Visual v) => IsAncestor(a, v);","tryCatchPattern":"try { var t = child.TransformToAncestor(anc); } catch (InvalidOperationException) { /* not ancestor/descendant */ }","preventionTips":["Verify ancestry chain before calling transform APIs","Recompute after layout changes","For 2D-in-3D, use Viewport2DVisual3D as intermediary"],"tags":["wpf","visual-tree","transform","not-an-ancestor"],"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"}