s&box/field-guide
the symptom, in your words

"PanelComponent uses OnTreeBuilt, not OnAfterTreeRender"

✓ verified on engine 26.07lane: Building UIposted
▸ SYMPTOM

You override OnAfterTreeRender(bool firstRender) on a class that @inherits PanelComponent. The build fails with:

snippet
CS0115: "no suitable method found to override"
▸ CAUSE

OnAfterTreeRender(bool) is a Panel / razor code-behind (.razor.cs) hook. PanelComponent has a different lifecycle. Its tree-rebuild hooks (confirmed in Sandbox.Engine.xml) are:

  • OnTreeBuilt() — parameterless, called after the tree has been built (any time the contents change).
  • OnTreeFirstBuilt() — parameterless, called once after the first build.
▸ FIX

Replace OnAfterTreeRender(bool) with OnTreeBuilt():

snippet
protected override void OnTreeBuilt()
{
    // Re-apply imperative state to @ref'd panels here.
    // The @ref is a NEW Panel object on each BuildHash-triggered
    // rebuild, so anything set imperatively (e.g. BackgroundImage)
    // must be re-applied here, not once.
}

Use OnTreeFirstBuilt() for one-time initialization that should happen after the first render tree build.

▸ WHY IT WORKS

PanelComponent and Panel share Razor rendering but have distinct C# base classes with different virtual methods. Mixing up the lifecycle hooks compiles against the wrong base — the error is immediate and clear, but the correct replacement isn't obvious without checking the engine XML.

Verified on engine 26.07 — seen in a real project.
s&box moves fast; an undated fix is a liability. Spot a stale detail?