stride3d/stride · error · InvalidOperationException
A part named 'PART_LogGridView' must be present in the…
Error message
A part named 'PART_LogGridView' must be present in the ControlTemplate, and must be of type 'DataGridControl'.
What it means
GridLogViewer.OnApplyTemplate retrieves its named template part PART_LogGridView and requires it to be a DataGridEx. If the applied ControlTemplate lacks that part or it is a different type, logGridView stays null and an InvalidOperationException is thrown, because the viewer cannot wire double-click handling and filters without the grid.
Solutions
- Add <stride:DataGridEx x:Name="PART_LogGridView"/> to the custom ControlTemplate for GridLogViewer
- Ensure the part's exact name 'PART_LogGridView' and type DataGridEx match TemplatePart contract
- Remove the custom template so the default one applies
Example fix
// before
<Style TargetType="controls:GridLogViewer">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:GridLogViewer">
<DataGrid x:Name="LogGrid"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
// after
<ControlTemplate TargetType="controls:GridLogViewer">
<controls:DataGridEx x:Name="PART_LogGridView"/>
</ControlTemplate> Defensive patterns
Strategy: try-catch
Validate before calling
var part = logViewer.Template.FindName("PART_LogGridView", logViewer) as DataGridEx;
if (part == null) throw new InvalidOperationException("Template must contain a DataGridEx named PART_LogGridView"); Type guard
static bool HasValidLogTemplate(GridLogViewer v) => v.FindVisualChildOfType<DataGridEx>(x => x.Name == "PART_LogGridView") != null;
Try / catch
try { logViewer.ApplyTemplate(); }
catch (InvalidOperationException ex) { log.Error("GridLogViewer template missing PART_LogGridView", ex); } Prevention
- Respect TemplatePart attributes when re-templating custom controls
- Keep the exact PART_ names and part types from the default template
- Smoke-test custom styles by applying them in a UI test
When it happens
Trigger: Applying a custom Style/ControlTemplate to GridLogViewer that omits the PART_LogGridView part, names it differently, or declares it as a type other than DataGridEx.
Common situations: Re-templating the control for styling and forgetting the template-part contract; renaming the part in XAML; using a DataGrid instead of DataGridEx in a custom template.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- The given window does not contain a ContentPresenter.
- A part named ' ' must be present in the ControlTemplate…
- 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…
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/b48b9885db724a01.
Report an issue: GitHub.
Appendix: source
Thrown at sources/editor/Stride.Core.Assets.Editor/View/Controls/GridLogViewer.cs:158
/// <summary>
/// Gets or sets whether the log viewer should display fatal messages.
/// </summary>
public bool ShowStacktrace { get { return (bool)GetValue(ShowStacktraceProperty); } set { SetValue(ShowStacktraceProperty, value); } }
/// <summary>
/// Gets or sets the session to use to select an asset related to a log message.
/// </summary>
public SessionViewModel Session { get { return (SessionViewModel)GetValue(SessionProperty); } set { SetValue(SessionProperty, value); } }
/// <inheritdoc/>
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
logGridView = GetTemplateChild("PART_LogGridView") as DataGridEx;
if (logGridView == null)
throw new InvalidOperationException("A part named 'PART_LogGridView' must be present in the ControlTemplate, and must be of type 'DataGridControl'.");
logGridView.MouseDoubleClick += GridMouseDoubleClick;
// We may have a bunch of messages appended before the logGridView was ready, let's present them now that it is
ApplyFilters();
}
private void GridMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
if (Session == null)
return;
var logMessage = logGridView.SelectedItem as AssetSerializableLogMessage;
if (logMessage != null && !string.IsNullOrEmpty(logMessage.AssetUrl))
{
var asset = Session.GetAssetById(logMessage.AssetId);
if (asset != null)
Session.ActiveAssetView.SelectAssetCommand.Execute(asset);View on GitHub (pinned to 96fad776d2)