1.9 KiB
1.9 KiB
Avalonia, Zafiro & Reactive Rules
Avalonia UI Rules
- Strict Avalonia: Never use
System.Drawing; always use Avalonia types. - Pure ViewModels: ViewModels must never reference Avalonia types.
- Bindings Over Code-Behind: Logic should be driven by bindings.
- DataTemplates: Prefer explicit
DataTemplates and typedDataContexts. - VisualStates: Avoid using
VisualStatesunless absolutely required.
Zafiro Guidelines
- Prefer Abstractions: Always look for existing Zafiro helpers, extension methods, and abstractions before re-implementing logic.
- Validation: Use Zafiro's
ValidationRuleand validation extensions instead of ad-hoc reactive logic.
DynamicData & Reactive Rules
The Mandatory Approach
- Operator Preference: Always prefer DynamicData operators (
Connect,Filter,Transform,Sort,Bind,DisposeMany) over plain Rx operators when working with collections. - Readable Pipelines: Build and maintain pipelines as a single, readable chain.
- Lifecycle: Use
DisposeWithfor lifecycle management. - Minimal Subscriptions: Subscriptions should be minimal, centralized, and strictly for side-effects.
Forbidden Anti-Patterns
- Ad-hoc Sources: Do NOT create new
SourceList/SourceCacheon the fly for local problems. - Logic in Subscribe: Do NOT place business logic inside
Subscribe. - Operator Mismatch: Do NOT use
System.Reactiveoperators if a DynamicData equivalent exists.
Canonical Patterns
Validation of Dynamic Collections:
this.ValidationRule(
StagesSource
.Connect()
.FilterOnObservable(stage => stage.IsValid)
.IsEmpty(),
b => !b,
_ => "Stages are not valid")
.DisposeWith(Disposables);
Filtering Nulls:
Use WhereNotNull() in reactive pipelines.
this.WhenAnyValue(x => x.DurationPreset).WhereNotNull()