stride3d/stride · error · ArgumentException
The dependency object to attach to the…
Error message
The dependency object to attach to the DependencyPropertyWatcher must be a FrameworkElement.
What it means
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.
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.
Example fix
// before
watcher.Attach((DependencyObject)myBrush); // ArgumentException
// after
if (target is FrameworkElement fe)
watcher.Attach(fe);
else
DependencyPropertyDescriptor.FromProperty(MyProperty, target.GetType())
.AddValueChanged(target, OnChanged); Defensive patterns
Strategy: type-guard
Validate before calling
if (dependencyObject is FrameworkElement)
watcher.Attach(dependencyObject);
else
UseDescriptorWatcher(dependencyObject, property, onChanged); Type guard
static bool IsAttachable(DependencyObject d) => d is FrameworkElement;
Try / catch
try { watcher.Attach(dependencyObject); }
catch (ArgumentException ex) when (ex.Message.Contains("must be a FrameworkElement")) { /* fall back to DependencyPropertyDescriptor-based watching */ } Prevention
- 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.
When it happens
Trigger: 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().
Common situations: 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.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Behavior of type ' ' must be bound to objects of type ' '…
- A dependency object is already attached to this instance of…
- Invalid ' ' TemplatePart type. ' ' expected.
- is not a numeric type
- The parameter of the ConvertBack method of this converter…
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/8791f0370e317b3d.
Report an issue: GitHub.
Appendix: source
Thrown at sources/presentation/Stride.Core.Presentation.Wpf/Core/DependencyPropertyWatcher.cs:43
public DependencyPropertyWatcher([NotNull] FrameworkElement attachTo)
{
Attach(attachTo);
}
public DependencyObject AssociatedObject => frameworkElement;
public void Attach([NotNull] DependencyObject dependencyObject)
{
if (dependencyObject == null) throw new ArgumentNullException(nameof(dependencyObject));
if (ReferenceEquals(dependencyObject, frameworkElement))
return;
if (frameworkElement != null)
throw new InvalidOperationException("A dependency object is already attached to this instance of DependencyPropertyWatcher.");
frameworkElement = dependencyObject as FrameworkElement;
if (frameworkElement == null)
throw new ArgumentException("The dependency object to attach to the DependencyPropertyWatcher must be a FrameworkElement.");
frameworkElement.Loaded += ElementLoaded;
frameworkElement.Unloaded += ElementUnloaded;
AttachHandlers();
}
public void Detach()
{
frameworkElement.Loaded -= ElementLoaded;
frameworkElement.Unloaded -= ElementUnloaded;
DetachHandlers();
handlers.Clear();
frameworkElement = null;
}
public void RegisterValueChangedHandler(DependencyProperty property, EventHandler handler)
{
handlers.Add(Tuple.Create(property, handler));View on GitHub (pinned to 96fad776d2)