{"record":{"id":"07507490f7d9436d","repo":"dotnet/wpf","slug":"updatedpi-should-only-be-called-on-the-root-of-a-visual-tree","errorCode":null,"errorMessage":"UpdateDPI should only be called on the root of a Visual tree","messagePattern":"UpdateDPI should only be called on the root of a Visual tree","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/VisualTreeHelper.cs","lineNumber":110,"sourceCode":"        /// </summary>\n        public static DpiScale GetDpi(Visual visual)\n        {\n            return visual.GetDpi();\n        }\n\n\n        /// <summary>\n        /// This method updates the DPI information of a visual. It can only be called on a Visual with no parent.\n        /// </summary>\n        public static void SetRootDpi(Visual visual, DpiScale dpiInfo)\n        {\n            if ((object)dpiInfo == null)\n            {\n                throw new NullReferenceException(\"dpiInfo cannot be null\");\n            }\n            if (visual.InternalVisualParent != null)\n            {\n                throw new InvalidOperationException(\"UpdateDPI should only be called on the root of a Visual tree\");\n            }\n            DpiFlags dpiFlags = DpiUtil.UpdateDpiScalesAndGetIndex(dpiInfo.PixelsPerInchX, dpiInfo.PixelsPerInchY);\n            visual.RecursiveSetDpiScaleVisualFlags(new DpiRecursiveChangeArgs(dpiFlags, visual.GetDpi(), dpiInfo));\n        }\n\n        /// <summary>\n        /// Visual parent of this Visual.\n        /// </summary>\n        public static DependencyObject GetParent(DependencyObject reference)\n        {\n            Visual visual;\n            Visual3D visual3D;\n\n            VisualTreeUtils.AsNonNullVisual(reference, out visual, out visual3D);\n\n            // x86 branch prediction skips the branch on first encounter.  We favor 2D.\n            if (visual3D != null)\n            {","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/VisualTreeHelper.cs#L92-L128","documentation":"VisualTreeHelper.SetRootDpi throws InvalidOperationException when the target visual has a parent (InternalVisualParent != null). Root DPI can only be set on the root of a visual tree; child DPI is derived from the parent, so setting it on a child would break the DPI inheritance invariant.","triggerScenarios":"Calling VisualTreeHelper.SetRootDpi on any visual that is already attached to a parent — e.g. calling it inside a loaded element's DPI handling instead of on the HwndSource root visual.","commonSituations":"Trying to update DPI in a UserControl or child element; calling SetRootDpi from a window's content element rather than the root; handling DpiChanged at the wrong tree level.","solutions":["Call SetRootDpi only on the root visual (e.g. the visual obtained from HwndSource.RootVisual or a top-level Popup root)","For child visuals, rely on automatic DPI inheritance or handle DpiChanged events instead","Check visual parentage first: only call when VisualTreeHelper.GetParent(visual) is null"],"exampleFix":"// before\nVisualTreeHelper.SetRootDpi(myUserControl, dpi); // throws: has parent\n// after\nvar source = PresentationSource.FromVisual(myWindow) as HwndSource;\nVisualTreeHelper.SetRootDpi(source.RootVisual, dpi);","handlingStrategy":"validation","validationCode":"if (VisualTreeHelper.GetParent(visual) != null)\n    throw new InvalidOperationException(\"SetRootDpi requires a root visual with no parent.\");","typeGuard":"bool IsRootVisual(Visual v) => VisualTreeHelper.GetParent(v) == null;","tryCatchPattern":"try { VisualTreeHelper.SetRootDpi(visual, dpi); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"root\")) { /* target the HwndSource.RootVisual instead */ }","preventionTips":["Only call SetRootDpi on HwndSource.RootVisual or other parentless roots","Handle DPI changes via DpiChanged events on the top-level source, not per-child calls","Remember child visuals inherit DPI; never set it manually on children"],"tags":["wpf","dpi","visual-tree","invalid-operation"],"backgroundTag":"invalid-state-transition","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"}