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

  1. Attach a FrameworkElement (Control, Panel, ContentElement host) instead of a plain DependencyObject.
  2. If the target is not an element, watch the property via DependencyPropertyDescriptor.AddValueChanged(depObj, property, handler) directly.
  3. 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

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


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)