the symptom, in your words

"@ref on a bare private field silently never assigns"

✓ verified on 26.07.08e
lane Building UIposted

▸ SYMPTOM

A Razor @ref binding targets a private field, the code compiles (maybe with a CS0649 "field is never assigned to" warning buried in the build log), and the ref is null at runtime forever. No error, no exception: the panel or element just never gets captured.

▸ CAUSE

The engine's Razor compiler resolves @ref bindings against the component's public API surface. A bare private field (Panel _myPanel;) isn't visible to the binding system, so the assignment silently no-ops. The only compiler signal is CS0649, which is easy to miss in a long build log and doesn't communicate the real problem.

Every working @ref in the engine's own source code binds to an auto-property, not a field.

▸ FIX

Change the field to a property:

snippet
// Bad - silently null forever
Panel _myPanel;

// Good - @ref binds correctly
Panel MyPanel { get; set; }

Then in Razor:

snippet
<Panel @ref="MyPanel" />

The { get; set; } auto-property is visible to the binding system and receives the assignment when the panel mounts.

▸ WHY IT WORKS

Razor @ref uses the component's property metadata to perform the assignment at render time. Properties expose a setter that the framework can invoke; bare fields (especially private ones) are invisible to this reflection-based binding. Using a property aligns with the engine's own pattern and guarantees the reference is populated.

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

Want to know when new guides or fixes drop? Join the community to help build this out. Report gotchas, flag outdated fixes, or just lurk.

Join the Discord