{"record":{"id":"8791f0370e317b3d","repo":"stride3d/stride","slug":"the-dependency-object-to-attach-to-the","errorCode":null,"errorMessage":"The dependency object to attach to the DependencyPropertyWatcher must be a FrameworkElement.","messagePattern":"The dependency object to attach to the DependencyPropertyWatcher must be a FrameworkElement\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"sources/presentation/Stride.Core.Presentation.Wpf/Core/DependencyPropertyWatcher.cs","lineNumber":43,"sourceCode":"        public DependencyPropertyWatcher([NotNull] FrameworkElement attachTo)\n        {\n            Attach(attachTo);\n        }\n\n        public DependencyObject AssociatedObject => frameworkElement;\n\n        public void Attach([NotNull] DependencyObject dependencyObject)\n        {\n            if (dependencyObject == null) throw new ArgumentNullException(nameof(dependencyObject));\n            if (ReferenceEquals(dependencyObject, frameworkElement))\n                return;\n\n            if (frameworkElement != null)\n                throw new InvalidOperationException(\"A dependency object is already attached to this instance of DependencyPropertyWatcher.\");\n            frameworkElement = dependencyObject as FrameworkElement;\n\n            if (frameworkElement == null)\n                throw new ArgumentException(\"The dependency object to attach to the DependencyPropertyWatcher must be a FrameworkElement.\");\n\n            frameworkElement.Loaded += ElementLoaded;\n            frameworkElement.Unloaded += ElementUnloaded;\n            AttachHandlers();\n        }\n\n        public void Detach()\n        {\n            frameworkElement.Loaded -= ElementLoaded;\n            frameworkElement.Unloaded -= ElementUnloaded;\n            DetachHandlers();\n            handlers.Clear();\n            frameworkElement = null;\n        }\n\n        public void RegisterValueChangedHandler(DependencyProperty property, EventHandler handler)\n        {\n            handlers.Add(Tuple.Create(property, handler));","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/presentation/Stride.Core.Presentation.Wpf/Core/DependencyPropertyWatcher.cs#L25-L61","documentation":"DependencyPropertyWatcher watches property changes on FrameworkElements so it can subscribe Loaded/Unloaded for lifetime management. Attach first null-checks the argument, then casts to FrameworkElement; if the supplied DependencyObject is not a FrameworkElement (e.g. a bare DependencyObject, DispatcherObject, or Freezable), it throws ArgumentException.","triggerScenarios":"Calling watcher.Attach(depObj) where depObj is a DependencyObject that is not a FrameworkElement — for example a DependencyPropertyHolder, a Freezable (Brush), or a plain DependencyObject created via new DependencyObject().","commonSituations":"Passing non-Element dependency objects (resources, brushes, animation holders) to watchers; code refactors where the tracked target changed type; watching properties on non-visual objects.","solutions":["Attach a FrameworkElement (Control, Panel, ContentElement host) instead of a plain DependencyObject.","If the target is not an element, watch the property via DependencyPropertyDescriptor.AddValueChanged(depObj, property, handler) directly.","Add a runtime check: if (depObj is FrameworkElement fe) watcher.Attach(fe); else use an alternate watching mechanism."],"exampleFix":"// before\nwatcher.Attach((DependencyObject)myBrush); // ArgumentException\n// after\nif (target is FrameworkElement fe)\n    watcher.Attach(fe);\nelse\n    DependencyPropertyDescriptor.FromProperty(MyProperty, target.GetType())\n        .AddValueChanged(target, OnChanged);","handlingStrategy":"type-guard","validationCode":"if (dependencyObject is FrameworkElement)\n    watcher.Attach(dependencyObject);\nelse\n    UseDescriptorWatcher(dependencyObject, property, onChanged);","typeGuard":"static bool IsAttachable(DependencyObject d) => d is FrameworkElement;","tryCatchPattern":"try { watcher.Attach(dependencyObject); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"must be a FrameworkElement\")) { /* fall back to DependencyPropertyDescriptor-based watching */ }","preventionTips":["Only pass Control/Panel/ContentElement-derived objects to Attach.","For non-visual DependencyObjects (Brushes, Freezables), use DependencyPropertyDescriptor.AddValueChanged.","Type targets as FrameworkElement in calling code so the compiler rejects non-elements."],"tags":["wpf","dependency-properties","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}