用途:该技能用于指导在 Avalonia UI 中创建自定义控件,包括 UserControl、TemplatedControl、基础绘图控件、自定义 Panel、控件库、附加属性和自定义 Flyout 等场景。核心思路是按复用需求选择控件类型。
主要能力与控件类型选择:
- UserControl:从 UserControl 继承,由现有控件组合而成的应用专用视图或页面。示例中 MyCard.axaml 使用 Border 包裹 ContentPresenter 并绑定内容;代码后置类需为 partial 并在构造函数中调用 InitializeComponent()。
- TemplatedControl:从 TemplatedControl 继承,无外观、可按主题重新样式化的可复用控件,适合控件库与主题。示例 RatingControl 通过 AvaloniaProperty.Register 注册 StyledProperty<int> Value;默认模板在 Themes/Generic.axaml 中以 ControlTheme 定义,并需提供 x:Key="{x:Type local:RatingControl}"。
- 基础控件:从 Control 继承,重写 Render(DrawingContext) 进行自定义绘制,适合图表、仪表、游戏等;示例 CircleControl 绘制椭圆并在 MeasureOverride 返回期望尺寸,通过 InvalidateVisual() 触发重绘。
- Panel:从 Panel 继承,实现自定义布局算法,需重写 MeasureOverride 与 ArrangeOverride;示例 CircularPanel 将子元素排布在圆周上。
属性系统:
- StyledProperty:支持样式、所有优先级的绑定与值继承,按优先级列表存储,适用于需要样式的大多数场景。
- DirectProperty:不支持样式,仅 LocalValue 绑定,按字段存储,适用于无需样式的高频属性,读写通过 SetAndRaise 配合字段实现。
- 附加属性:使用 AvaloniaProperty.RegisterAttached 注册,并提供静态 Get/Set 方法,可在 XAML 中以 local:MyHelper.IsHighlighted="True" 形式使用。
- 模板部件:在 OnApplyTemplate(TemplateAppliedEventArgs e) 中通过 e.NameScope.Find<T>("PART_X") 获取,11.3/12.x 保持不变。
版本变化(12.0):
- 渲染 API:DrawingContext.PushPreTransform、PushPostTransform、PushTransformContainer 替换为 PushTransform(matrix);BindingPriority.TemplatedParent 改为 Template;ILockedFramebuffer 增加 AlphaFormat 字段,新 LockedFramebuffer 构造函数需要 AlphaFormat 参数;Bitmap.CopyPixels 的 alpha 格式改由 ILockedFramebuffer 提供;IReadableBitmapWithAlphaImpl 改为 IReadableBitmapImpl.AlphaFormat;CreateOffscreenRenderTarget 参数由 (PixelSize, double) 改为 (PixelSize, Vector, bool);Layoutable.GetMaxSizeFromConstraint 由私有改为 protected 可重写。Render() 中的 DrawEllipse、DrawRectangle、DrawGeometry、DrawText 用法不变,标准 RenderTargetBitmap 代码不受影响。
- 数据验证:绑定插件(BindingPlugins、IDataValidationPlugin 等)被移除,数据注解验证默认关闭;以 enableDataValidation: true 注册的属性会自动报告错误,应移除仅调用 DataValidationErrors.SetError 的 UpdateDataValidation 重写,仅在为某属性抑制默认行为时重写并跳过基类调用。
- 样式键:IStyleable(Type IStyleable.StyleKey)在 12 中移除,统一使用 StyleKeyOverride(11.3 亦可用);如 protected override Type StyleKeyOverride => typeof(Button) 可让控件沿用 Button 的 ControlTheme;泛型约束应放在 StyledElement 上而非 IStyleable。
控件库项目:
- 使用独立的类库项目,引用 Avalonia NuGet 包而非 Avalonia.Desktop。
- 将 Generic.axaml 作为嵌入资源,路径形如 avares://MyLib/Themes/Generic.axaml。
- 在使用方应用中通过 <StyleInclude Source="avares://MyLib/Themes/Generic.axaml"/> 注册。
社区辅助工具:
- HotAvalonia:控件开发期间 AXAML 热重载。
- Avant Garde(GitHub: kuiperzone/AvantGarde):面向控件库的独立 XAML 预览器。
- ShowMeTheXaml.Avalonia:运行时展示渲染后的 XAML,便于演示。
- Avalonia.Xaml.Behaviors:无需子类化即可为控件附加行为,支持 EventTriggerBehavior、InvokeCommandAction、DataTriggerBehavior、ChangePropertyAction 等,是 WPF DataTrigger 与 EventTrigger 的替代方案。
- Sortable.Avalonia:为 ItemsControl 提供拖放排序行为。
常见错误:
- 沿用 WPF 习惯从 Control 继承实现无外观控件,而非使用 TemplatedControl。
- UserControl 构造函数中未调用 InitializeComponent()。
- UserControl 类缺少 partial 关键字。
- 对不需要样式的高频属性使用 StyledProperty 造成性能问题。
- 在 12.x 中仍实现 IStyleable 或使用 BindingPriority.TemplatedParent、PushPreTransform。
- Generic.axaml 的 ControlTheme 缺少 x:Key="{x:Type local:MyControl}"。
适用场景与限制:适合熟悉 C# 与 XAML、需要在 Avalonia 中扩展控件或构建控件库的开发者;需要理解属性系统与渲染流程。资料未提供安装命令、价格、性能数据或具体版本支持范围等信息。