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

  1. Add <stride:DataGridEx x:Name="PART_LogGridView"/> to the custom ControlTemplate for GridLogViewer
  2. Ensure the part's exact name 'PART_LogGridView' and type DataGridEx match TemplatePart contract
  3. 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

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


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)