Avalonia跨平台上位机控件开发之水泵

随着国产化的推进,越来越多的开发者选择使用跨平台的框架来创建上位机应用,而Avalonia正是一个优秀的选择。本文将探讨如何利用Avalonia框架进行水泵控件的开发,并重点记录在开发的过程中所碰到的一些问题。

控件的构成

水泵控件主要在控件的内部需要创建一个旋转的动画来表示水泵当前的运行状态,在没有工作时为静止状态没有任何动画,当水泵启动时会对中间的部分进行连续的旋转。运行效果如下:

动画的创建

在控件中为了方便控制旋转动画的编写,我这边使用了一个Canvas将需要旋转的部分包裹在其中,这样在制作动画的时候直接对这个Canvas进行旋转就可以了,否则要旋转部分的Path的坐标数据为相对于最外层Canvas的坐标进行绘制,此时要找到旋转中心是一个很困难的事情。同时为这个Canvas指定了一个名称,方便后续在制作动画时的Selector处理。

<Canvas
Canvas.Left="19.5"
Canvas.Top="39.5"
Height="34.5"
Name="BumpCircle"
UseLayoutRounding="False"
Width="34.2">
<Path
Fill="#ffffffff"
Stroke="#ff6c6c6c"
StrokeJoin="Miter"
StrokeThickness="2.05166">
<Path.Data>
<PathGeometry Figures="M 11.3573 15.4557 C 6.78011 13.3704 4.04416 9.6096 3.14943 4.1733 M 11.3573 19.7314 C 6.82241 21.3797 2.37649 20.6383 -1.98048 17.5071 M 15.4612 22.6354 C 13.3753 27.2112 9.61334 29.9464 4.17541 30.8408 M 19.7381 22.6354 c 1.64889 4.53351 0.907239 8.97809 -2.22494 13.3338 m 5.12991 -17.4365 c 4.57717 2.08531 7.31313 5.84611 8.20786 11.2824 M 22.6431 14.2571 c 4.53487 -1.64839 8.98079 -0.906966 13.3378 2.22428 M 18.5392 11.353 c 2.08594 -4.5758 5.84787 -7.31093 11.2858 -8.20539 m -15.5627 8.20539 c -1.64889 -4.53351 -0.907239 -8.97809 2.22494 -13.3338 m 4.50314 14.9864 c 2.20369 2.20302 2.20369 5.77484 0 7.97786 c -2.20369 2.20302 -5.77658 2.20302 -7.98027 0 c -2.20369 -2.20302 -2.20369 -5.77484 0 -7.97786 c 2.20369 -2.20302 5.77658 -2.20302 7.98027 0 m 9.43124 -9.4284 c 7.41241 7.41018 7.41241 19.4245 0 26.8347 c -7.41241 7.41019 -19.4304 7.41019 -26.8428 0 c -7.41241 -7.41018 -7.41241 -19.4245 0 -26.8347 c 7.41241 -7.41019 19.4304 -7.41019 26.8428 0" />
</Path.Data>
</Path>
</Canvas>

动画的部分定义了一个伪类running,用来表示当前水泵已经处在了运行状态。因此在进行动画编写的时候先使用一下Selector选择伪类为running

<Style Selector="controls|Pump.running">

然后需要选择到我们需要需要进行动画的部分,使用如下的Selector进行选择

<Style Selector="^ /template/ Canvas#BumpCircle">

^ : 继承上一层Selector

/template/ :进入到控件内部的Template

Canvas#BumpCircle:选择名字为BumpCircle的Canvas

使用Selector选择到需要动画的控件部分后就可以进行动画的编写,动画的完整代码如下:

<Style Selector="controls|Pump.running">
<Style Selector="^ /template/ Canvas#BumpCircle">
<Style.Animations>
<Animation Duration="0:0:5" IterationCount="INFINITE">
<KeyFrame Cue="0%">
<Setter Property="RotateTransform.Angle" Value="0" />
</KeyFrame>
<KeyFrame Cue="100%">
<Setter Property="RotateTransform.Angle" Value="360" />
</KeyFrame>
</Animation>
</Style.Animations>
</Style>
</Style>

以上代码创建了一个0到360度的旋转动画。

踩到的坑

创建伪类时的一个小知识点

当在avalonia中使用伪类的时候经常会碰到:pointerover等内置的一些伪类,而要使用Selector来选择这些伪类的时候通常我们会使用

<Style Selector="Button:pointerover"/>

但是当我们定义了一个自定义的伪类时,比如上面控件用到的running,此时我们在使用Selector的时候需要使用如下格式

<Style Selector="Pump.running"/>

在平时的开发中要注意以上的一些不同

在属性改变时为控件添加伪类

为了表示控件的运行状态,我在控件的C#代码中添加了一个名为Running的StyledProperty,用这个属性来区分水泵的运行状态,因此我需要在Running属性进行修改的时候为控件添加或移除running伪类。而为了方便测试我将这个Running绑定至了Checkbox的IsChecked属性,代码如下:

<CheckBox
Canvas.Left="600"
Canvas.Top="250"
Name="CheckBox">
运行状态
</CheckBox> <controls:Pump
Canvas.Left="600"
Canvas.Top="100"
Height="100"
Running="{Binding #CheckBox.IsChecked}"
Width="100" />

开始时我将伪类的创建与移除代码编写在Runing属性的set中进行处理,代码如下:

    public bool? Running
{
get => GetValue(RunningProperty);
set
{
SetValue(RunningProperty, value);
if (value == true)
{
PseudoClasses.Add("running");
}
else
{
PseudoClasses.Remove("running");
}
}
}

但是以上的代码在CheckBox的IsChecked属性变更时并没有办法触发到set方法,导致动画无法被触发。

经过一段时间的摸索正确的做法为在OnPropertyChanged方法中进行相关的处理,代码如下:

    protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change); if (change.Property == RunningProperty)
{
if (change.NewValue != null && (bool)change.NewValue)
{
PseudoClasses.Add("running");
}
else
{
PseudoClasses.Remove("running");
}
}
}

总结

在本文中,我们探讨了如何利用Avalonia框架开发水泵控件,并详细介绍了控件构成、动画创建及开发过程中的一些问题和解决方案。通过使用Canvas包裹可旋转部分,我们简化了动画实现,同时利用伪类管理水泵的运行状态,使得控件的交互性和视觉效果得到了有效提升。

我们还分享了在创建自定义伪类时的一些注意事项,以及如何在属性变更时动态更新伪类的实现。这个过程强调了Avalonia框架在构建灵活、跨平台的用户界面方面的强大能力。

希望这篇文章能够为开发者在使用Avalonia进行控件开发时提供一些实用的参考和启发,助力他们更好地实现工业自动化中的各类应用。无论是初学者还是经验丰富的开发者,都可以在这个过程中获得新的见解和技巧。让我们共同期待在Avalonia上实现更多的创意与创新!

控件的完整代码由于内容较多,请至文章底部的控件代码链接自行获取。

欢迎关注我的公众号“nodered-co”,原创技术文章第一时间推送。

Style Selector Syntax

How To Bind to a Contro

控件代码

Avalonia跨平台上位机控件开发之水泵的更多相关文章

  1. C# Winform开发以及控件开发的需要注意的,被人问怕了,都是基础常识

    我是搞控件开发的,经常被人问,所以把一些问题记录了下来!如果有人再问,直接把地址丢给他看. 一. 经常会有人抱怨Winform界面闪烁,下面有几个方法可以尽可能的避免出现闪烁 1.控件的使用尽量以纯色 ...

  2. C#ActiveX控件开发学习

    一:C#ActiveX控件开发注意事项   1:C#开发的ActiveX控件只可在装有Framework的系统上才能用. 2:只有IE浏览器支持. 3:初次安装需要导入代码签名证书及其证书链的方式, ...

  3. asp.net控件开发基础(1)(转)原文更多内容

    asp.net本身提供了很多控件,提供给我们这些比较懒惰的人使用,我认为控件的作用就在此,因为我们不想重复工作,所以要创建它,这个本身便是一个需求的关系,所以学习控件开发很有意思. wrox网站上有本 ...

  4. 利用ArcGIS Engine、VS .NET和Windows控件开发GIS应用

    Dixon 原文  用ArcGIS Engine.VS .NET和Windows控件开发GIS应用     此过程说明适合那些使用.NET建立和部署应用的开发者,它描述了使用ArcGIS控件建立和部署 ...

  5. Asp.Netserver控件开发的Grid实现(三)列编辑器

    以下是GridColumnsEditor的实现代码: GridColumnsEditor.cs using System; using System.Collections.Generic; usin ...

  6. ASP.NET2.0组件控件开发视频 初体验

    原文:ASP.NET2.0组件控件开发视频 初体验 ASP.NET2.0组件控件开发视频 初体验 录了视频,质量不是很好,大家体验下.我会重新录制的 如果不清楚,可以看看http://v.youku. ...

  7. ASP.NET自定义控件组件开发 第五章 模板控件开发

    原文:ASP.NET自定义控件组件开发 第五章 模板控件开发 第五章 模板控件开发 系列文章链接: ASP.NET自定义控件组件开发 第一章 待续 ASP.NET自定义控件组件开发 第一章 第二篇 接 ...

  8. ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl

    原文:ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl 第四章 组合控件开发CompositeControl 大家好,今天我们来实现一个自定义的控件,之前我们已经 ...

  9. ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl 后篇 --事件冒泡

    原文:ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl 后篇 --事件冒泡 CompositeControl  后篇 --事件冒泡 系列文章链接: ASP.NET ...

  10. WinForm控件开发总结目录

    WinForm控件开发总结(一)------开篇 WinForm控件开发总结(二)------使用和调试自定义控件 WinForm控件开发总结(三)------认识WinForm控件常用的Attrib ...

随机推荐

  1. 2023上海理工大学校内选拔赛A-D题

    前言 不要在意标题,既然是随记,就随性点() 今天参加了2023年中国高校计算机大赛-团队程序设计天梯赛(GPLT)上海理工大学校内选拔赛(同步赛)_ACM/NOI/CSP/CCPC/ICPC算法编程 ...

  2. 2023 CCPC 桂林题解

    gym H. Sweet Sugar 一个经典贪心是从下到上,如果子树 \(u\) 剩下的部分(一定包含 \(u\))包含合法连通块,那么这个连通块给答案贡献 \(1\),切断 \(u\) 与 \(f ...

  3. 【粉丝问答20】Linux内核定时器使用及其他时间操作

    问题描述 如何使用内核定时器? 内核定时器 Linux内核定时器是timer_list,下面我们详细介绍定时器的使用. 1. 简介 内核定时器是内核用来控制在未来某个时间点(基于jiffies)调度执 ...

  4. GC终结标记 SuspendEE 是怎么回事

    一:背景 1. 讲故事 写这篇是起源于训练营里有位朋友提到了一个问题,在 !t -special 输出中有一个 SuspendEE 字样,这个字样在 coreclr 中怎么弄的?输出如下: 0:000 ...

  5. UVA11367 Full Tank?

    优先队列bfs 1 #include<cmath> 2 #include<queue> 3 #include<cstdio> 4 #include<strin ...

  6. Mac安装Adobe PS_AE_PR等系列软件提示错误代码146怎么办?

    在安装Mac版Adobe系列软件的时候,不管PS.AE.PR.AI等,如果出现错误代码146,下面两个方法能够轻松解决. 解决方法一:需要我们打开「系统设置」-「隐私与安全」-「App管理」,打开「i ...

  7. 修改 Ubuntu 文件夹为英文

    如果你在安装 Ubuntu 时,语言选了中文,那么系统自动创建的文件夹也会是中文(下载.图片 等).有时这会造成不便.可以通过以下命令将文件夹改为英文: LANG=C LC_ALL=C xdg-use ...

  8. 【YashanDB知识库】列与存储过程中重名变量/别名问题

    问题现象 当一条查询中出现了重复别名,或者在一个存储过程中出现了变量名称与查询中别名相同,就会报错.这个问题在多个客户现场出现. create table test_tab1 (c1 int, c2 ...

  9. dotnet 读 WPF 源代码笔记 从 WM_POINTER 消息到 Touch 事件

    本文记录我读 WPF 源代码的笔记,在 WPF 底层是如何从 Win32 的消息循环获取到的 WM_POINTER 消息处理转换作为 Touch 事件的参数 由于 WPF 触摸部分会兼顾开启 Poin ...

  10. JDBC——案例

    创建一个商品表 drop table if exists tb_brand; -- 创建tb_brand表 create table tb_brand( id int primary key auto ...