Composite Family¶
When To Use It¶
Use CompositeVM<VM> when the parent owns an ordered homogeneous child list and
one child may be current. Tabs, note lists, result lists, and other "collection
plus selection" workflows belong here.
Use the modeled composite when children are projected from models during construction instead of being provided directly.
Shape And Ownership¶
CompositeVM adds one core concept on top of a collection container:
Currentmay be one child ornull
Everything else follows from that contract: guarded selection helpers,
foreground updates of IsCurrent, and optional builder hooks for initial
selection and current-changed callbacks.
Lifecycle And Messaging¶
The composite owns both child lifecycle and selection messaging:
construct()waits for every child before the composite reports constructeddestruct()clearsCurrentbefore destructing childrenCurrentchanges publish the parentCurrentproperty and the affected children'sIsCurrentAsyncSelection(true)routes selection work through the foreground dispatcher
Cross-Language Surface¶
| Concept | C# | Python | TypeScript | Swift |
|---|---|---|---|---|
| Type | CompositeVM<VM> |
CompositeVM[VM] |
CompositeVM<VM> |
CompositeVM<VM> |
| Modeled type | CompositeVM<M, VM> |
CompositeVMOf[M, VM] |
CompositeVMOf<M, VM> |
CompositeVMOf<M, VM> |
| Selection slot | Current |
current |
current |
current |
| Initial selector hook | Current(selector) |
current(selector) |
current(selector) |
current(selector) |
Example¶
var tabs = CompositeVM<ComponentVM<TabModel>>.Builder()
.Name("tab-bar")
.Services(hub, dispatcher)
.Children(() => new[] { home, settings })
.Build();
tabs = (
CompositeVM[ComponentVMOf[TabModel]]
.builder()
.name("tab-bar")
.services(hub, dispatcher)
.children(lambda: [home, settings])
.build()
)
const tabs = CompositeVM.builder<ComponentVMOf<TabModel>>()
.name("tab-bar")
.services(hub, dispatcher)
.children(() => [home, settings])
.build();
let tabs = try CompositeVM<ComponentVMOf<TabModel>>.builder()
.name("tab-bar")
.services(hub: hub, dispatcher: dispatcher)
.children { [home, settings] }
.build()
Common Pitfalls¶
- Using a composite for recursive trees.
HierarchicalVMcarries the tree semantics directly. - Forgetting that
Currentmust always be a contained child ornull. - Assuming add-after-construct auto-constructs by default. It does not unless
AutoConstructOnAdd(true)is enabled. - Updating selection predicates without wiring current-changed triggers into commands that depend on selection.