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
- Add a RepeatButton named PART_DecreaseButton to the ControlTemplate
- Verify the exact, case-sensitive part name
- Use RepeatButton specifically (auto-repeat relies on it)
- 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
- Both increase and decrease buttons are mandatory — do not strip one
- Keep exact case-sensitive x:Name values
- Validate templates after style merges or theme changes
- Test both visible and collapsed template variants
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
- A part named ' ' must be present in the ControlTemplate…
- A part named ' ' must be present in the ControlTemplate…
- A part named ' ' must be present in the ControlTemplate…
- A part named 'PART_ContentHost' must be present in the…
- A part named 'PART_IncreaseButton' must be present in the…
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)