dotnet/maui · error · InvalidOperationException

Cannot change a binding while it's applied

Error message

Cannot change a binding while it's applied

What it means

Thrown by ThrowIfApplied() (called from many property setters) when IsApplied is true, meaning the BindingBase has already been attached to a target BindableObject. MAUI bindings are not designed to be mutated after application; setters call ThrowIfApplied to enforce this invariant.

Source

Thrown at src/Controls/src/Core/BindingBase.cs:160

		/// </remarks>
		public static void EnableCollectionSynchronization(IEnumerable collection, object context, CollectionSynchronizationCallback callback)
		{
			if (collection == null)
				throw new ArgumentNullException(nameof(collection));
			if (callback == null)
				throw new ArgumentNullException(nameof(callback));

			SynchronizedCollections.Add(collection, new CollectionSynchronizationContext(context, callback));
		}

		/// <summary>Throws <see cref="InvalidOperationException" /> if the binding has already been applied.</summary>
		/// <remarks>Used by property setters to prevent mutation after the binding has been attached to a target.</remarks>
		/// <exception cref="InvalidOperationException">The binding has already been applied.</exception>
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		protected void ThrowIfApplied()
		{
			if (IsApplied)
				throw new InvalidOperationException("Cannot change a binding while it's applied");
		}

		internal virtual void Apply(bool fromTarget)
				=> IsApplied = true;

		internal virtual void Apply(object context, BindableObject bindObj, BindableProperty targetProperty, bool fromBindingContextChanged, SetterSpecificity specificity)
			=> IsApplied = true;

		internal abstract BindingBase Clone();

		internal virtual object GetSourceValue(object value, Type targetPropertyType)
		{
			if (value == null && TargetNullValue != null)
				return TargetNullValue;

			if (StringFormat != null && TryFormat(StringFormat, value, out var formatted))
				return formatted;

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Create a fresh Binding instance whenever configuration must change; never mutate an applied binding.
  2. Set all desired properties before calling SetBinding on the target.
  3. Call RemoveBinding / re-create the binding rather than editing properties in place.

Example fix

// before — mutating after apply
element.SetBinding(Label.TextProperty, binding);
binding.StringFormat = "{0:C}"; // throws

// after
var binding = new Binding("Price") { StringFormat = "{0:C}" };
element.SetBinding(Label.TextProperty, binding);
Defensive patterns

Strategy: validation

Validate before calling

// Configure fully BEFORE applying; never mutate after SetBinding
var binding = new Binding("Name")
{
    Mode = BindingMode.OneWay,
    StringFormat = "{0}"
};
element.SetBinding(Label.TextProperty, binding);

Prevention

When it happens

Trigger: Setting Mode, Path, Converter, Source, StringFormat, or any other property on a Binding after it has been applied to a BindableObject via SetBinding. Reusing the same Binding instance and mutating it after it is live. Applying a binding then trying to reconfigure it in a handler.

Common situations: Caching a Binding instance and reconfiguring it on view reuse. Setting binding properties inside an event handler that fires after the binding is already attached. Misunderstanding that SetBinding finalizes the binding.

Related errors


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