PrismLibrary/Prism · error · InvalidOperationException

Resources.HostControlCannotBeSetAfterAttach

Error message

Resources.HostControlCannotBeSetAfterAttach

What it means

RegionManagerRegistrationBehavior.HostControl setter throws InvalidOperationException with Resources.HostControlCannotBeSetAfterAttach when the behavior is already attached (IsAttached == true). The host control is the target the behavior monitors, so changing it after attach would leave the region registration in an inconsistent state.

Solutions

  1. Set HostControl before calling Attach(); create a new behavior instance if the host must change.
  2. Reorder initialization code so HostControl is assigned first and Attach() is last.
  3. Detach the old behavior (IsAttached false) and build a fresh one for a new host control.
  4. Avoid binding HostControl to a property that changes after the region attaches.

Example fix

// before
behavior.Attach();
behavior.HostControl = newHost; // throws
// after
behavior.HostControl = newHost;
behavior.Attach();
Defensive patterns

Strategy: validation

Validate before calling

if (behavior.IsAttached)
    throw new InvalidOperationException("HostControl must be set before Attach().");

Type guard

bool CanSetHostControl(RegionManagerRegistrationBehavior b) => !b.IsAttached;

Try / catch

try
{
    behavior.HostControl = host;
}
catch (InvalidOperationException)
{
    // behavior already attached — create a new behavior for this host
    behavior = new RegionManagerRegistrationBehavior { RegionManager = rm, RegionName = name, HostControl = host };
    behavior.Attach();
}

Prevention

When it happens

Trigger: Setting behavior.HostControl after behavior.Attach() has run — e.g., resolving the behavior from a region's Behaviors collection and reassigning its HostControl, or data-binding/two-way assignments that fire after attach.

Common situations: Custom region setup code that reuses behavior instances across controls; XAML templates recreating the visual host while reusing the behavior; test code manipulating behaviors directly after attach.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of PrismLibrary/Prism@358118cd64 (2026-09-15). Data as JSON: /api/errors/62967b74f7c1f1fb. Report an issue: GitHub.

Appendix: source

Thrown at src/Wpf/Prism.Wpf/Navigation/Regions/Behaviors/RegionManagerRegistrationBehavior.cs:55

        public IRegionManagerAccessor RegionManagerAccessor { get; set; }

        /// <summary>
        /// Gets or sets the <see cref="DependencyObject"/> that the <see cref="IRegion"/> is attached to.
        /// </summary>
        /// <value>A <see cref="DependencyObject"/> that the <see cref="IRegion"/> is attached to.
        /// This is usually a <see cref="FrameworkElement"/> that is part of the tree.</value>
        /// <exception cref="InvalidOperationException">When this member is set after the <see cref="IRegionBehavior.Attach"/> method has being called.</exception>
        public DependencyObject HostControl
        {
            get
            {
                return hostControl;
            }
            set
            {
                if (IsAttached)
                {
                    throw new InvalidOperationException(Resources.HostControlCannotBeSetAfterAttach);
                }

                hostControl = value;
            }
        }

        /// <summary>
        /// When the <see cref="IRegion"/> has a name assigned, the behavior will start monitoring the ancestor controls in the element tree
        /// to look for an <see cref="IRegionManager"/> where to register the region in.
        /// </summary>
        protected override void OnAttach()
        {
            if (string.IsNullOrEmpty(Region.Name))
            {
                Region.PropertyChanged += Region_PropertyChanged;
            }
            else
            {

View on GitHub (pinned to 358118cd64)