stride3d/stride · error · InvalidOperationException
A part named ' ' must be present in the ControlTemplate…
Error message
A part named '{GridPartName}' must be present in the ControlTemplate, and must be of type '{typeof(Grid).FullName}'. What it means
CanvasView.OnApplyTemplate retrieves the mandatory template part named by GridPartName and requires it to be a Grid, storing it to host the rendering canvas. If GetTemplateChild returns null or a non-Grid, the control cannot function and throws InvalidOperationException. This enforces the control/template contract for custom templates.
Solutions
- Add a Grid named with GridPartName ('PART_Grid'-style key) inside the custom ControlTemplate.
- Ensure the element with that name is of type Grid, not another panel.
- Start from the default template in the theme dictionary and modify without removing the named part.
Example fix
<!-- before: custom template missing part --> <ControlTemplate TargetType="controls:CanvasView"> <Border/> </ControlTemplate> <!-- after --> <ControlTemplate TargetType="controls:CanvasView"> <Grid x:Name="PART_Grid"/> </ControlTemplate>
Defensive patterns
Strategy: validation
Validate before calling
var grid = control.Template?.FindName("PART_Grid", control) as Grid;
if (grid == null) throw new InvalidOperationException("Custom CanvasView template lacks the required Grid part."); Type guard
bool HasGridPart(CanvasView view) => view.Template?.FindName("PART_Grid", view) is Grid; Try / catch
try { control.ApplyTemplate(); }
catch (InvalidOperationException ex) { log.Error("CanvasView template invalid", ex); } Prevention
- Copy the default CanvasView template and edit without removing named parts.
- Keep the Grid part name identical to GridPartName and its type exactly Grid.
- Add a smoke test applying the custom template before release.
When it happens
Trigger: Applying a ControlTemplate for CanvasView that lacks the required named Grid part, names it differently, or hosts an element of another type (e.g. Border) under that name.
Common situations: Restyling CanvasView with a custom template based on a generic.xaml copy that was edited; renaming the part; template not yet applied when code runs.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- A part named 'PART_EditableTextBox' must be present in the…
- A part named 'PART_ListBox' must be present in the…
- A part named 'PART_TrimmedText' must be present in the…
- A part named 'PART_LogTextBox' must be present in the…
- A part named 'PART_LogGridView' must be present in the…
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/0189633e85fd94ae.
Report an issue: GitHub.
Appendix: source
Thrown at sources/presentation/Stride.Core.Presentation.Wpf/Controls/CanvasView/CanvasView.cs:101
{
var view = (CanvasView)sender;
var model = e.OldValue as IDrawingModel;
model?.Detach(view);
model = e.NewValue as IDrawingModel;
model?.Attach(view);
view.InvalidateDrawing();
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
grid = GetTemplateChild(GridPartName) as Grid;
if (grid == null)
throw new InvalidOperationException($"A part named '{GridPartName}' must be present in the ControlTemplate, and must be of type '{typeof(Grid).FullName}'.");
var canvas = new Canvas();
grid.Children.Add(canvas);
canvas.UpdateLayout();
renderer = new CanvasRenderer(canvas);
}
protected override Size ArrangeOverride(Size arrangeBounds)
{
if (ActualWidth > 0 && ActualHeight > 0)
{
if (Interlocked.CompareExchange(ref this.isDrawingInvalidated, 0, 1) == 1)
{
UpdateVisuals();
}
}
return base.ArrangeOverride(arrangeBounds);View on GitHub (pinned to 96fad776d2)