stride3d/stride · error · InvalidOperationException

Behavior of type ' ' must be bound to objects of type ' '…

Error message

Behavior of type '{GetType()}' must be bound to objects of type '{typeof(FrameworkElement)}'. (currently bound to object typed '{AssociatedObject.GetType()}')

What it means

The behavior subscribes to focus events and manipulates bindings via BindingOperations, which requires the associated object to be a FrameworkElement. If AssociatedObject cannot be cast to FrameworkElement, OnAttached throws InvalidOperationException explaining the required type and the actual type of the bound object.

Solutions

  1. Move the behavior to a FrameworkElement (e.g. the TextBox/Control itself) inside Interaction.Behaviors.
  2. If the target is inside a template, attach the behavior to the templated root FrameworkElement, not to a non-element node.
  3. Adjust code-behind attachment so the behavior is attached to a Control/FrameworkElement instance.

Example fix

<!-- before: behavior on a non-FrameworkElement node -->
<GradientStop>
  <i:Interaction.Behaviors>
    <b:OnFocusBindingInterruptionBehavior PropertyName="Color" Binding="{Binding Accent}" />
  </i:Interaction.Behaviors>
</GradientStop>

<!-- after: attach to the hosting control -->
<TextBox Text="{Binding Accent}">
  <i:Interaction.Behaviors>
    <b:OnFocusBindingInterruptionBehavior PropertyName="Text" Binding="{Binding Accent}" />
  </i:Interaction.Behaviors>
</TextBox>
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(associatedObject is FrameworkElement))
    throw new InvalidOperationException($"Behavior requires a FrameworkElement; got {associatedObject?.GetType().Name}.");

Type guard

static bool CanHostFocusBehavior(DependencyObject o) => o is FrameworkElement;

Try / catch

try { AttachBehavior(behavior, host); }
catch (InvalidOperationException ex) when (ex.Message.Contains("must be bound to objects of type")) { log.Error($"Move behavior to a FrameworkElement, not {host.GetType().Name}"); }

Prevention

When it happens

Trigger: Attaching OnFocusBindingInterruptionBehavior to a non-FrameworkElement such as a Freezable, BindingExpression target like a BindingMarker, a DependencyObject in a template that isn't an element, or collection items that are plain DependencyObjects.

Common situations: Dropping the behavior onto the wrong node in a template (e.g. on a GradientStop or a non-visual DependencyObject); using i:Interaction on objects where only triggers are legal; wiring the behavior in code to a generic DependencyObject.

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/07a752d2bff63df0. Report an issue: GitHub.

Appendix: source

Thrown at sources/presentation/Stride.Core.Presentation.Wpf/Behaviors/OnFocusBindingInterruptionBehavior.cs:54

                throw new ArgumentException("PropertyName must be set.");

            if (Binding == null)
            {
                throw new ArgumentException($"Binding must be set for {PropertyName} property of host '{AssociatedObject}' on behavior '{GetType().FullName}'.");
            }

            property = AssociatedObject.GetDependencyProperties(true).FirstOrDefault(dp => dp.Name == PropertyName);

            if (property == null /* need to check DesignMode as well ? */)
                throw new InvalidOperationException($"Impossible to find property named '{PropertyName}' on object typed '{AssociatedObject.GetType()}'.");

            if ((Binding is Binding) == false)
                throw new InvalidOperationException("Not supported binding type.");

            var element = AssociatedObject as FrameworkElement;
            if (element == null)
            {
                throw new InvalidOperationException(
                    $"Behavior of type '{GetType()}' must be bound to objects of type '{typeof(FrameworkElement)}'. (currently bound to object typed '{AssociatedObject.GetType()}')");
            }

            BindingOperations.SetBinding(AssociatedObject, property, Binding);

            // subscribe to *Focus events
            element.GotFocus += OnHostGotFocus;
            element.LostFocus += OnHostLostFocus;

            subscriber = new AnonymousDisposable(() =>
            {
                // unsubscribe from *Focus events
                element.LostFocus -= OnHostLostFocus;
                element.GotFocus -= OnHostGotFocus;
            });
        }

        protected override void OnDetaching()

View on GitHub (pinned to 96fad776d2)