stride3d/stride · error · InvalidOperationException
A part named 'PART_ContentHost' must be present in the…
Error message
A part named 'PART_ContentHost' must be present in the ControlTemplate, and must be of type 'ScrollViewer'.
What it means
NumericTextBox.OnApplyTemplate requires a ScrollViewer named 'PART_ContentHost' that hosts the editable text. When the applied template lacks it or uses a different element type, GetTemplateChild returns null and an InvalidOperationException is thrown.
Solutions
- Add <ScrollViewer x:Name="PART_ContentHost"/> to the ControlTemplate (it must contain the text host)
- Keep the exact case-sensitive name PART_ContentHost
- Ensure the element is a ScrollViewer, not another container type
- Derive your template from the default NumericTextBox template
Example fix
<!-- before --> <Grid> <TextBox x:Name="PART_ContentHost"/> </Grid> <!-- after --> <Grid> <ScrollViewer x:Name="PART_ContentHost"/> </Grid>
Defensive patterns
Strategy: validation
Validate before calling
var host = numericTextBox.Template?.FindName("PART_ContentHost", numericTextBox) as ScrollViewer;
if (host == null) throw new InvalidOperationException("NumericTextBox template missing PART_ContentHost (ScrollViewer)"); Type guard
bool HasContentHost(NumericTextBox c) => c.Template?.FindName("PART_ContentHost", c) is ScrollViewer; Try / catch
try { control.ApplyTemplate(); }
catch (InvalidOperationException ex) { log.Error(ex, "Invalid NumericTextBox template; restoring default style"); control.Style = null; } Prevention
- Always include a ScrollViewer named PART_ContentHost in templates
- Do not replace the host with TextBox/ContentPresenter directly
- Re-validate templates when upgrading the library
- Smoke-test editable behavior with custom themes
When it happens
Trigger: Custom ControlTemplate for NumericTextBox without a ScrollViewer named PART_ContentHost; part renamed; replaced with a TextBox or ContentPresenter directly.
Common situations: Re-skinning numeric editors and omitting the content host; templates derived from plain TextBox styles that name the host differently; edits that convert the ScrollViewer into a Border.
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_DecreaseButton' 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/a8b53d1eda8e6c72.
Report an issue: GitHub.
Appendix: source
Thrown at sources/presentation/Stride.Core.Presentation.Wpf/Controls/NumericTextBox.cs:275
/// </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)
{
}
/// <inheritdoc/>View on GitHub (pinned to 96fad776d2)