stride3d/stride · error · InvalidOperationException

A part named 'PART_DecreaseButton' must be present in the…

Error message

A part named 'PART_DecreaseButton' must be present in the ControlTemplate, and must be of type 'RepeatButton'.

What it means

NumericTextBox.OnApplyTemplate requires the template part 'PART_DecreaseButton' of type RepeatButton for step-down behavior. A ControlTemplate missing that part, misnaming it, or substituting a different control type makes GetTemplateChild return null and triggers this InvalidOperationException.

Solutions

  1. Add a RepeatButton named PART_DecreaseButton to the ControlTemplate
  2. Verify the exact, case-sensitive part name
  3. Use RepeatButton specifically (auto-repeat relies on it)
  4. Copy the default template as the starting point

Example fix

<!-- before -->
<Grid>
  <RepeatButton x:Name="PART_IncreaseButton"/>
</Grid>
<!-- after -->
<Grid>
  <RepeatButton x:Name="PART_IncreaseButton"/>
  <RepeatButton x:Name="PART_DecreaseButton"/>
</Grid>
Defensive patterns

Strategy: validation

Validate before calling

var btn = numericTextBox.Template?.FindName("PART_DecreaseButton", numericTextBox) as RepeatButton;
if (btn == null) throw new InvalidOperationException("NumericTextBox template missing PART_DecreaseButton (RepeatButton)");

Type guard

bool HasDecreaseButton(NumericTextBox c) => c.Template?.FindName("PART_DecreaseButton", c) is RepeatButton;

Try / catch

try { control.ApplyTemplate(); }
catch (InvalidOperationException ex) { log.Error(ex, "Invalid NumericTextBox template; restoring default style"); control.Style = null; }

Prevention

When it happens

Trigger: Applying a custom ControlTemplate without a RepeatButton named PART_DecreaseButton; wrong x:Name casing; element replaced with Button/TextBox.

Common situations: Custom numeric editor skins; template copies from older versions after renames; deleting the decrease button because only increment is needed — both parts are mandatory.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/652c7794690ecb47. Report an issue: GitHub.

Appendix: source

Thrown at sources/presentation/Stride.Core.Presentation.Wpf/Controls/NumericTextBox.cs:271

        public event EventHandler<RepeatButtonPressedRoutedEventArgs> RepeatButtonPressed { add { AddHandler(RepeatButtonPressedEvent, value); } remove { RemoveHandler(RepeatButtonPressedEvent, value); } }

        /// <summary>
        /// Raised when one of the repeat button is released.
        /// </summary>
        public event EventHandler<RepeatButtonPressedRoutedEventArgs> RepeatButtonReleased { add { AddHandler(RepeatButtonReleasedEvent, value); } remove { RemoveHandler(RepeatButtonReleasedEvent, value); } }

        /// <inheritdoc/>
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            increaseButton = GetTemplateChild("PART_IncreaseButton") as RepeatButton;
            if (increaseButton == null)
                throw new InvalidOperationException("A part named 'PART_IncreaseButton' must be present in the ControlTemplate, and must be of type 'RepeatButton'.");

            decreaseButton = GetTemplateChild("PART_DecreaseButton") as RepeatButton;
            if (decreaseButton == null)
                throw new InvalidOperationException("A part named 'PART_DecreaseButton' must be present in the ControlTemplate, and must be of type 'RepeatButton'.");

            contentHost = GetTemplateChild("PART_ContentHost") as ScrollViewer;
            if (contentHost == null)
                throw new InvalidOperationException("A part named 'PART_ContentHost' must be present in the ControlTemplate, and must be of type 'ScrollViewer'.");

            var increasePressedWatcher = new DependencyPropertyWatcher(increaseButton);
            increasePressedWatcher.RegisterValueChangedHandler(ButtonBase.IsPressedProperty, RepeatButtonIsPressedChanged);
            var decreasePressedWatcher = new DependencyPropertyWatcher(decreaseButton);
            decreasePressedWatcher.RegisterValueChangedHandler(ButtonBase.IsPressedProperty, RepeatButtonIsPressedChanged);
            var textValue = FormatValue(Value);

            SetCurrentValue(TextProperty, textValue);
        }

        /// <summary>
        /// Raised when the <see cref="Value"/> property has changed.
        /// </summary>
        protected virtual void OnValueChanged(double? oldValue, double? newValue)

View on GitHub (pinned to 96fad776d2)