当前位置: 首页 > news >正文

从 WPF 到 Avalonia 的迁移系列实战篇4:控件模板与 TemplatedControl

从 WPF 到 Avalonia 的迁移系列实战篇4:控件模板与 TemplatedControl

我的GitHub仓库Avalonia学习项目包含完整的Avalonia实践案例与代码对比。
我的gitcode仓库是Avalonia学习项目

在前几篇中,我们聊过了依赖属性、路由事件、资源等迁移相关的基础,这一篇我们进入 自定义控件开发
如果你在 WPF 中做过复杂控件,就一定绕不开 Control + ControlTemplate 的组合。

那么问题来了:

Avalonia 中,我们该如何实现类似的机制?

答案就是 —— TemplatedControl

为了直观演示,我写了一个小 Demo:自定义一个 三角形控件(TriangleControl),让它自动闪烁。我们分别用 WPFAvalonia 来实现,最后对比一下两者的异同。


一、为什么要用 TemplatedControl?

在 UI 框架里,我们有两种常见的自定义控件方式:

  1. UserControl

    • 逻辑 + UI 写在一起
    • 简单场景够用,但换皮肤、换模板比较困难
  2. TemplatedControl(WPF 中就是 Control)

    • 逻辑(C#)和外观(XAML 模板)解耦
    • 控件类只负责属性和逻辑,不关心 UI 长什么样
    • 外观完全交给 ControlTemplate 控制

例如 WPF 的 Button,内部逻辑并不知道它有边框还是圆角,这些都由 ControlTemplate 决定。
Avalonia 完全继承了这一思想,只不过对应的基类换成了 TemplatedControl


二、WPF 版 TriangleControl

在 WPF 中,我们继承 Control,通过 OnApplyTemplate() 获取模板里的元素,然后对它做动画。

控件类

public class TriangleControl : Control
{private Path? _path;static TriangleControl(){DefaultStyleKeyProperty.OverrideMetadata(typeof(TriangleControl),new FrameworkPropertyMetadata(typeof(TriangleControl)));}public static readonly DependencyProperty FillProperty =DependencyProperty.Register(nameof(Fill), typeof(Brush),typeof(TriangleControl), new PropertyMetadata(Brushes.Black));public Brush Fill{get => (Brush)GetValue(FillProperty);set => SetValue(FillProperty, value);}public override void OnApplyTemplate(){base.OnApplyTemplate();if (_path != null){// 避免重复应用模板导致多次动画_path.ClearValue(UIElement.OpacityProperty);}_path = GetTemplateChild("PART_Path") as Path;if (_path != null){var blinkAnimation = new DoubleAnimation{From = 1.0,To = 0.2,Duration = TimeSpan.FromSeconds(0.5),AutoReverse = true,RepeatBehavior = RepeatBehavior.Forever};_path.BeginAnimation(UIElement.OpacityProperty, blinkAnimation);}}
}

样式模板

<ResourceDictionaryxmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:controls="clr-namespace:WpfDemo.controls"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><Style TargetType="{x:Type controls:TriangleControl}"><Setter Property="Width" Value="50" /><Setter Property="Height" Value="50" /><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type controls:TriangleControl}"><Viewbox Stretch="Fill"><PathData="M 0,1 L 0.5,0 L 1,1 Z"Fill="{TemplateBinding Fill}"Stretch="Uniform"x:Name="PART_Path" /></Viewbox></ControlTemplate></Setter.Value></Setter></Style>
</ResourceDictionary>

效果:一个三角形控件,透明度循环闪烁。


三、Avalonia 版 TriangleControl

在 Avalonia 中,流程几乎一模一样:

  • 继承 TemplatedControl
  • 属性用 StyledProperty<T>
  • 模板元素通过 e.NameScope.Find<T>() 获取
  • 动画系统换成 Animation + KeyFrame

控件类

public class TriangleControl : TemplatedControl
{private Path? _path;public static readonly StyledProperty<IBrush> FillProperty =AvaloniaProperty.Register<TriangleControl, IBrush>(nameof(Fill), Brushes.Black);public IBrush Fill{get => GetValue(FillProperty);set => SetValue(FillProperty, value);}protected override void OnApplyTemplate(TemplateAppliedEventArgs e){base.OnApplyTemplate(e);_path = e.NameScope.Find<Path>("PART_Path");if (_path != null){var animation = new Animation{Duration = TimeSpan.FromSeconds(1),IterationCount = IterationCount.Infinite,Easing = new SineEaseInOut(),Children ={new KeyFrame{Cue = new Cue(0),Setters = { new Setter(Visual.OpacityProperty, 1.0) }},new KeyFrame{Cue = new Cue(0.5),Setters = { new Setter(Visual.OpacityProperty, 0.2) }},new KeyFrame{Cue = new Cue(1),Setters = { new Setter(Visual.OpacityProperty, 1.0) }}}};animation.RunAsync(_path, CancellationToken.None);}}
}

样式模板

<Stylesxmlns="https://github.com/avaloniaui"xmlns:controls="clr-namespace:AvaloniaDemo.Controls"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><Design.PreviewWith><controls:TriangleControl /></Design.PreviewWith><Style Selector="controls|TriangleControl"><Setter Property="Width" Value="50" /><Setter Property="Height" Value="50" /><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="controls:TriangleControl"><Viewbox Stretch="Uniform"><PathData="M 0,1 L 0.5,0 L 1,1 Z"Fill="{TemplateBinding Fill}"Stretch="Uniform"x:Name="PART_Path" /></Viewbox></ControlTemplate></Setter.Value></Setter></Style>
</Styles>

效果:与 WPF 一致,三角形控件透明度闪烁。


四、WPF vs Avalonia 对比分析

下面是一个详细对比表格:

功能点WPFAvalonia
基类ControlTemplatedControl
依赖属性DependencyPropertyStyledProperty<T>
应用模板方法OnApplyTemplate()OnApplyTemplate(TemplateAppliedEventArgs)
查找模板元素GetTemplateChild("PART_X")e.NameScope.Find<T>("PART_X")
模板绑定{TemplateBinding ...}{TemplateBinding ...}(完全一致)
动画系统Storyboard / DoubleAnimationAnimation / KeyFrame

可以看到:

  • 整体思想几乎完全一致,因此从 WPF 迁移过来没有学习门槛
  • Avalonia 在语法上更简洁,比如属性直接用 StyledProperty,不需要 DependencyProperty.Register 那么啰嗦
  • 动画系统的 API 不同,但用法也很直观

五、心得体会

通过这个 Demo,我们发现:

  • WPF 和 Avalonia 在自定义控件的核心思路上保持了高度一致性

  • 只要你熟悉 WPF 的 ControlTemplate 模型,迁移到 Avalonia 基本无缝

  • 不同点主要体现在:

    1. API 命名(DependencyPropertyStyledProperty
    2. 模板元素查找方式
    3. 动画系统

因此,掌握 TemplatedControl = 掌握 Avalonia 自定义控件的核心

✍️ 结语
如果你正打算从 WPF 迁移到 Avalonia,不妨从这种简单的自定义控件开始练手。理解了 TemplatedControl,你就掌握了 Avalonia 的控件扩展基础。

我的GitHub仓库Avalonia学习项目包含完整的Avalonia实践案例与代码对比。
我的gitcode仓库是Avalonia学习项目

http://www.dtcms.com/a/359554.html

相关文章:

  • AIA中断控制器IPI的Linux内核实现
  • 【Flask】测试平台开发,产品管理功能UI重构-第九篇
  • 应用开发使用缓存
  • R notes[2]
  • VMware虚拟机网盘下载与安装指南(附安装包)
  • GaRe:面向非约束户外照片集的可重光照 3D 高斯溅射技术简要解析
  • Python与Rust语法对比详解:从入门到精通
  • Day19_【机器学习—线性回归 (1)】
  • Linux-搭建NFS服务器
  • Hutool DsFactory多数据源切换
  • 深度学习篇---MobileNet网络结构
  • 揭秘数据分组的智慧:Self-Constrained Clustering Ensemble 介绍
  • leetcode_240 搜索二维矩阵 II
  • Windows PostgreSQL JDBC驱动安装包位置
  • 基于开源AI大模型、AI智能名片与S2B2C商城小程序的“教育用户”模式探究
  • C数据结构:排序
  • Knit-易用的prompt管理和调试工具
  • 程序员独立开发直播卖产品 SOP 教程
  • 下载 | Win10正式版最新原版ISO系统映像 (22H2、19045.6282、多合一版本)-系统问题修复
  • Spring Boot 3.0 应用 HTTP 到 HTTPS 技术改造方案
  • AI 相关内容:Agent、MCP、Prompt 与 RAG 入门指南
  • VSCode `tasks.json` 中 `tasks` 数组的详细解析
  • AI 应用 图文 解说 (二) -- 百度智能云 ASR LIM TTS 语音AI助手源码
  • VSCode的launch.json配置文件在C++项目调试中的全面应用
  • React学习教程,从入门到精通, ReactJS - 架构(6)
  • 心路历程-基础命令3
  • 编程与数学 03-004 数据库系统概论 11_数据库的维护
  • OpenCV 图像处理实战与命令行参数配置:从轮廓检测到模板匹配
  • 嵌入式Linux RAMDisk驱动开发
  • 介绍Ansible和实施Ansible PlayBook