[ PROMPT_NODE_23734 ]
avalonia-reactive-rules
[ SKILL_DOCUMENTATION ]
# Avalonia, Zafiro & Reactive Rules
## Avalonia UI 规则
- **严格的 Avalonia**: 永远不要使用 `System.Drawing`;始终使用 Avalonia 类型。
- **纯粹的 ViewModels**: ViewModels **绝对不能**引用 Avalonia 类型。
- **绑定优于 Code-Behind**: 逻辑应由绑定驱动。
- **DataTemplates**: 优先使用显式的 `DataTemplate` 和强类型的 `DataContext`。
- **VisualStates**: 除非绝对必要,否则避免使用 `VisualStates`。
## Zafiro 指南
- **优先使用抽象**: 在重新实现逻辑之前,始终寻找现有的 Zafiro 辅助工具、扩展方法和抽象。
- **验证**: 使用 Zafiro 的 `ValidationRule` 和验证扩展,而不是临时的响应式逻辑。
## DynamicData & 响应式规则
### 强制性方法
- **运算符偏好**: 在处理集合时,始终优先使用 **DynamicData** 运算符(`Connect`, `Filter`, `Transform`, `Sort`, `Bind`, `DisposeMany`),而不是普通的 Rx 运算符。
- **可读的管道**: 构建并维护单一、可读的链式管道。
- **生命周期**: 使用 `DisposeWith` 进行生命周期管理。
- **最小化订阅**: 订阅应尽可能少、集中,且仅用于副作用。
### 禁止的反模式
- **临时数据源**: 不要为了解决局部问题而即时创建新的 `SourceList` / `SourceCache`。
- **在 Subscribe 中编写逻辑**: 不要将业务逻辑放在 `Subscribe` 内部。
- **运算符不匹配**: 如果存在 DynamicData 等效项,请勿使用 `System.Reactive` 运算符。
### 规范模式
**动态集合的验证:**
csharp
this.ValidationRule(
StagesSource
.Connect()
.FilterOnObservable(stage => stage.IsValid)
.IsEmpty(),
b => !b,
_ => "Stages are not valid")
.DisposeWith(Disposables);
**过滤空值:**
在响应式管道中使用 `WhereNotNull()`。
csharp
this.WhenAnyValue(x => x.DurationPreset).WhereNotNull()