# Custom ViewModels and Computed bindings The shared **Bindings → Discover targets** panel now identifies the declared Model, selected ViewModel and Controller, lists custom properties, and shows public zero-argument application methods as Computed sources. **Find Converters / Validate** and the automatic preview gate validate existing Direct and Computed declarations in both hosts. The subsequent [Computed-binding inspector](computed-binding-inspector.md) also uses this validation for declarations authored in the shared form. ## Runtime selection and property precedence Discovery reads NeitzelLib's `@ViewModelClass` on the FXML Controller. For Component `fx:root` documents it uses the captured resource path (`package/ClassName.fxml`) to identify the Component class, which is also the Controller. The worker receives this identity from the same unambiguous source-root mapping used for draft overlays. The root's actual Component class supplies its target properties, including additions beyond its FXML base type. An unavailable Component class/context is reported as unresolved; a conflicting `fx:controller` on Component FXML is an error. With no explicit selection, discovery uses generic ViewModel capabilities, independent of incidental runtime reuse from another View. A subclass adds public no-argument accessors returning JavaFX `Property` to the inherited Model Attributes. Runtime precedence is preserved: reserved `latestMessage` wins, then Model Attributes, then additional property accessors. Generic nested Model paths also expose their message property. A replacement exposes only its own named JavaFX property API; it does not inherit Model Attributes, built-in message properties or dotted traversal through plain objects. The selected class must be concrete and have a constructor accepting the declared Model. The most-specific compatible constructor is checked for access from NeitzelLib's module; incomparable overloads produce an ambiguity warning. No constructor or accessor runs during discovery. An overridden `ViewModel.property(String)` is dynamic: signature-derived results remain unverified and produce warnings. Raw/generic property signatures that cannot establish a value type stay unresolved. Read-only ObservableValue accessors are not advertised as bindable ViewModel properties, matching the runtime's requirement for `Property`. ## Computed validation Discovery excludes Object methods and inherited JDK/JavaFX framework methods from the application-method inventory. Void and parameterized methods are unavailable as sources. Public inherited application methods are included. Method bodies never run during discovery. Validation checks the declared Controller, public zero-argument method, reflective accessibility to NeitzelLib, target fx:id, writable JavaFX property, duplicate Direct/Computed targets and boxed return-type assignability. Private `@FXML` methods are not sufficient for NeitzelLib Computed bindings. Object or unresolved value types yield warnings; missing methods, void results and known incompatible types are errors. Existing unprefixed method names remain accepted because the runtime also accepts them; the inventory displays `#method`. Computed validation still runs when a Model declaration is missing: that limits Model discovery but does not hide a known Controller-method error. Errors block new previews while saving invalid drafts and normal host Undo/Redo remain available. Results retain build/draft freshness checks. Pending target discovery can also satisfy an automatic preview-validation request, avoiding replacement of the user's discovery operation by a canvas refresh. ## Boundaries Application classes stay in the target worker and are loaded without initialization. The `bindings-v3` capability and metadata format 3 add Controller/ViewModel identity and Computed signatures, plus the captured resource on requests. Old metadata capabilities are rejected rather than silently decoded. Existing protocol identities, payload limits, path/target limits and worker cancellation apply; the method inventory is bounded to 256 entries. Generated metadata, custom BeanInfo execution, arbitrary dynamic property resolvers, full generic inference, cross-View first-use conflicts, nested ViewModel selection caused by other Views/Components, collection authoring and dependency-injection viability remain outside this slice. Method bodies, null results, constructor side effects and Computed refresh behavior are runtime concerns; compatible signatures do not prove that application code will succeed. In particular, discovery does not change which additional properties NeitzelLib observes for Computed refresh. Complete IDE Problems integration remains later work. ## Automated qualification Unit checks cover subclass/replacement selection, inherited properties and methods, name precedence, built-in messages, constructor mismatch, dynamic resolvers, Component resource identity/root properties, method accessibility and return types, missing Model declarations and non-initialization. Real classpath and named-module fixtures check custom, replacement and Component metadata without initializing application classes. Separate fresh target processes load subclass/replacement Views through NeitzelLib, exercise custom-property write-back, confirm Model-name precedence and execute Computed methods. Shared host contracts verify resource identity through the worker transport. Live standalone and registered IntelliJ checks inspect custom properties and methods, save a type-invalid Computed binding, verify preview blocking and exact Undo/Redo, and discover replacement properties without mutating FXML. Existing rendering, Converter, input and lifecycle checks remain enabled. No manual test is required; previously skipped human checks remain skipped. Qualification completed on 2026-11-13 on the pinned macOS baseline: `check-bootstrap.py` passed with **91 unit/adapter tests** (84 Maven, 7 IntelliJ), **36 fresh target processes / 484 fixture assertions**, both native standalone launch modes, both connected host adapters and **48 worker lifecycle cycles**. `check-ide-host.py` passed the registered IntelliJ editor scenarios for both classpath and module-path applications, including exclusive JavaFX 26 native-library verification and worker shutdown. No manual testing was used. Local run evidence: `/tmp/viewmodel-bootstrap.log`, `/tmp/viewmodel-registered-ide.log`, `target/connected-workflow/` and `target/ide-workflow/{classpath,modulepath}.json`. Malformed-XML diagnostics are intentional recovery-test inputs. No uncaught application exception or native crash was found in these qualification runs. This is evidence for the pinned baseline, not a broader platform certification.