{"record":{"id":"652c7794690ecb47","repo":"stride3d/stride","slug":"a-part-named-part-decreasebutton-must-be-present-in-the","errorCode":null,"errorMessage":"A part named 'PART_DecreaseButton' must be present in the ControlTemplate, and must be of type 'RepeatButton'.","messagePattern":"A part named 'PART_DecreaseButton' must be present in the ControlTemplate, and must be of type 'RepeatButton'\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/presentation/Stride.Core.Presentation.Wpf/Controls/NumericTextBox.cs","lineNumber":271,"sourceCode":"        public event EventHandler<RepeatButtonPressedRoutedEventArgs> RepeatButtonPressed { add { AddHandler(RepeatButtonPressedEvent, value); } remove { RemoveHandler(RepeatButtonPressedEvent, value); } }\n\n        /// <summary>\n        /// Raised when one of the repeat button is released.\n        /// </summary>\n        public event EventHandler<RepeatButtonPressedRoutedEventArgs> RepeatButtonReleased { add { AddHandler(RepeatButtonReleasedEvent, value); } remove { RemoveHandler(RepeatButtonReleasedEvent, value); } }\n\n        /// <inheritdoc/>\n        public override void OnApplyTemplate()\n        {\n            base.OnApplyTemplate();\n\n            increaseButton = GetTemplateChild(\"PART_IncreaseButton\") as RepeatButton;\n            if (increaseButton == null)\n                throw new InvalidOperationException(\"A part named 'PART_IncreaseButton' must be present in the ControlTemplate, and must be of type 'RepeatButton'.\");\n\n            decreaseButton = GetTemplateChild(\"PART_DecreaseButton\") as RepeatButton;\n            if (decreaseButton == null)\n                throw new InvalidOperationException(\"A part named 'PART_DecreaseButton' must be present in the ControlTemplate, and must be of type 'RepeatButton'.\");\n\n            contentHost = GetTemplateChild(\"PART_ContentHost\") as ScrollViewer;\n            if (contentHost == null)\n                throw new InvalidOperationException(\"A part named 'PART_ContentHost' must be present in the ControlTemplate, and must be of type 'ScrollViewer'.\");\n\n            var increasePressedWatcher = new DependencyPropertyWatcher(increaseButton);\n            increasePressedWatcher.RegisterValueChangedHandler(ButtonBase.IsPressedProperty, RepeatButtonIsPressedChanged);\n            var decreasePressedWatcher = new DependencyPropertyWatcher(decreaseButton);\n            decreasePressedWatcher.RegisterValueChangedHandler(ButtonBase.IsPressedProperty, RepeatButtonIsPressedChanged);\n            var textValue = FormatValue(Value);\n\n            SetCurrentValue(TextProperty, textValue);\n        }\n\n        /// <summary>\n        /// Raised when the <see cref=\"Value\"/> property has changed.\n        /// </summary>\n        protected virtual void OnValueChanged(double? oldValue, double? newValue)","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/presentation/Stride.Core.Presentation.Wpf/Controls/NumericTextBox.cs#L253-L289","documentation":"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.","triggerScenarios":"Applying a custom ControlTemplate without a RepeatButton named PART_DecreaseButton; wrong x:Name casing; element replaced with Button/TextBox.","commonSituations":"Custom numeric editor skins; template copies from older versions after renames; deleting the decrease button because only increment is needed — both parts are mandatory.","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"],"exampleFix":"<!-- before -->\n<Grid>\n  <RepeatButton x:Name=\"PART_IncreaseButton\"/>\n</Grid>\n<!-- after -->\n<Grid>\n  <RepeatButton x:Name=\"PART_IncreaseButton\"/>\n  <RepeatButton x:Name=\"PART_DecreaseButton\"/>\n</Grid>","handlingStrategy":"validation","validationCode":"var btn = numericTextBox.Template?.FindName(\"PART_DecreaseButton\", numericTextBox) as RepeatButton;\nif (btn == null) throw new InvalidOperationException(\"NumericTextBox template missing PART_DecreaseButton (RepeatButton)\");","typeGuard":"bool HasDecreaseButton(NumericTextBox c) => c.Template?.FindName(\"PART_DecreaseButton\", c) is RepeatButton;","tryCatchPattern":"try { control.ApplyTemplate(); }\ncatch (InvalidOperationException ex) { log.Error(ex, \"Invalid NumericTextBox template; restoring default style\"); control.Style = null; }","preventionTips":["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"],"tags":["wpf","controltemplate","xaml"],"backgroundTag":"schema-validation-failed","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}