dotnet/maui · error · InvalidOperationException

Binding instances cannot be reused

Error message

Binding instances cannot be reused

What it means

Thrown by BindingExpression.Apply when the weak reference to a previously-bound target resolves to a different BindableObject than the one now being applied. MAUI Binding instances are single-use for a given target; reusing one against a different target throws to prevent corrupted state.

Source

Thrown at src/Controls/src/Core/BindingExpression.cs:90

  				// In a DataTemplate, x:DataType describes the item context - not the type of the referenced element.
   				// RelativeBindingSource is excluded: a mismatch against its source type must still be reported.
				bool skipTypeMismatchCheck = (source is not null && source is not RelativeBindingSource)
					|| !RuntimeFeature.IsXamlCBindingWithSourceCompilationEnabled;
				if (!skipTypeMismatchCheck)
				{
					if (sourceObject != null && !dataType.IsAssignableFrom(sourceObject.GetType()))
					{
						BindingDiagnostics.SendBindingFailure(Binding, "Binding", $"Mismatch between the specified x:DataType ({dataType}) and the current binding context ({sourceObject.GetType()}).");
						sourceObject = null;
					}
				}
			}

			_targetProperty = property;
			_specificity = specificity;

			if (_weakTarget != null && _weakTarget.TryGetTarget(out BindableObject prevTarget) && !ReferenceEquals(prevTarget, target))
				throw new InvalidOperationException("Binding instances cannot be reused");

			if (_weakSource != null && _weakSource.TryGetTarget(out var previousSource) && !ReferenceEquals(previousSource, sourceObject))
				throw new InvalidOperationException("Binding instances cannot be reused");

			_weakSource = new WeakReference<object>(sourceObject);
			_weakTarget = new WeakReference<BindableObject>(target);

			ApplyCore(sourceObject, target, property, false, specificity);
		}

		internal void Unapply()
		{
			if (_weakSource != null && _weakSource.TryGetTarget(out var sourceObject))
			{
				for (var i = 0; i < _parts.Count - 1; i++)
				{
					BindingExpressionPart part = _parts[i];

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Create a separate Binding instance per target; never share a single instance across controls.
  2. Use Clone() if you need an equivalent binding for a new target.
  3. In recycling scenarios, build bindings in the template/data-selectors rather than caching instances.

Example fix

// before — one binding, two targets
var b = new Binding("Name");
label1.SetBinding(Label.TextProperty, b);
label2.SetBinding(Label.TextProperty, b); // throws

// after
label1.SetBinding(Label.TextProperty, new Binding("Name"));
label2.SetBinding(Label.TextProperty, new Binding("Name"));
Defensive patterns

Strategy: validation

Validate before calling

// Never reuse; create per target
static Binding Make(string path) => new Binding(path);
label1.SetBinding(Label.TextProperty, Make("Name"));
label2.SetBinding(Label.TextProperty, Make("Name"));

Prevention

When it happens

Trigger: Calling SetBinding with the same Binding instance on two different BindableObject targets. Sharing a cached Binding across multiple controls. Re-applying a binding recovered from a pooled view to a new view instance.

Common situations: Storing a Binding in a static/field and applying it to multiple dynamically created controls. View recycling logic that reuses binding objects along with views. Copying bindings from a template element to siblings.

Related errors


AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13). Data as JSON: /api/errors/d8394da5ef6fb7e2. Report an issue: GitHub.