首页 > 技术文章 > Avalonia开发小结(持续更新)

wzwyc 2021-05-13 16:23 原文

官网:

https://avaloniaui.net/

源码:

https://github.com/AvaloniaUI/Avalonia

 

最近因为要研究跨平台开发,不可避免地顺带了解了Linux系统,把联想平板电脑装成了Ubuntu 20.04系统。

就像Linux系统一样,目前对它的了解是,将就着能用,但不是很好用。期间会遇到奇奇怪怪的各种小问题。

就像我的平板,外接的键盘带触摸板。因为打字的时候很容易触碰到触摸板,所以想把它禁用掉。但是这个在Windows系统很容易解决的小问题,可是在Linux下面可能根本无法解决,或者无法找到解决的方法。

但是这种小问题,其实又是非常影响平常的使用体验的。

 

这几天,把原来在Windows平板上用WPF开发的一些小程序都移植成了Avalonia版本。几个应用折腾下来,感觉还行,做东西还算是方便的,虽然跟WPF比可能还是有很大差距。

本身因为还没有正式发布,所以肯定还会存在一些问题。

但开发过程中遇到的很多问题,其实很多都是对Avalonia平台和Linux操作系统不是很熟悉。

就像游戏打怪一样,WPF换到了Avalonia,一些经验需要重新积累,其实还是需要几个项目做下来,慢慢地知道了哪些能做,哪些不能做。然后慢慢地扩展功能,积累新经验。

最关键的是,.net平台的跨平台开发,除了Avalonia之外,也没有更好的选择。作为用惯了WPF开发的码农来说,Avalonia应该是目前能找到的最好的代替品。

 

这几天都是在Ubuntu上用Rider来开发,比VS Code应该要好用一点,但是Rider的很多操作都跟VS不一样,也是一个慢慢熟悉的过程。

 

网上能找到的资料不多,但是很保贵。初次接触这个平台可以先看一下官网的帮助文档。

遇到问题,我一般会去项目的Github的issues搜索一下,可能会有线索。

剩下的百度谷歌,各种想办法。

再不行,看Avalonia的源码,看能不能解决。 

目前不支持的功能

  • 托盘图标
  • 没有ToolBar功能
  • 不支持全局热键
  • 不支持在前面XAML界面注册事件

目前遇到无法解决的问题

  • TextBox中\t制表符显示乱码的问题,目前还不知道怎么解决。

一些缺点

  •  生成的软件包会比较大,因为要带个各个系统的各种类库。

编辑器推荐

  • Visual Studio 2019

需要安装一个插件,但是XAML界面下,代码提示功能比较弱,基本上算没有,写起来不是很方便。

  • JetBrains Rider

目前最新版本是2021版本,本身是商用,可以试用30天。XAML的编辑提示功能会比VS2019要好,不过代码调试有时候没VS2019方便,可以两个IDE结合起来使用。

如果是在Linux系统下开发,因为没有VS编译器可用,感觉JetBrains Rider会是最好的选择,相比较VS Code,集成度会更高,代码提示等方面都会做得更好一点。

系统测试情况

目前试了一下,能够正常运行的系统,除了Windows系统外,流行的Ubuntu,Centos,Redhat这些系统应该都没啥问题。

国产的麒麟系统,之前有同事在中标麒麟上跑成功过,不过是默认的HelloWord应用。

后面我在优麒麟上也是运行成功过,但是复杂一点的应用,能正常编译,但是运行的时候会报错:Default font family name can't be null or empty.

在现在用的Ubuntu 20.04操作系统上,其实也遇到这个font family的问题,通过网上提供的方法,是可以解决和正常运行的。

不过尽量先不要用iconfont,用了以后在Windows系统下可能会没有问题,但是在报字体错误的系统下,可能要修改一下那个自定义的字体控制的类。

因为我现在还不知道怎么改,所以采用了最省事的方法,放弃使用iconfont。

 

Avalonia的应用可以打包成deb安装包。也可以基于软件包设置桌面图标,操作方法参考:

Ubuntu系统下为Avalonia应用创建桌面图标 - wzwyc - 博客园

https://www.cnblogs.com/wzwyc/p/14820893.html

 

常见问题解决

1、Ubuntu系统下TextBox中文显示乱码

貌似Avalonia必须指定一下当前窗体的字体,不然中文就是会显示乱码,之前是直接设置成“Microsoft YaHei”,会导致Ubuntu系统下找不到相应的字体:

private static string GetPlatformFontFamily()
{
    if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
    {
        return "Microsoft YaHei";
    }
    else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
    {
        return "Menlo"; //换成OSX下的中文字体
    }
    else
    {
        return "Noto Sans CJK SC";
    }
}

 

2、ToolTip的显示

在要显示ToolTip的控件上加上附加属性:

ToolTip.Tip="Tip内容"

 

3、Ubuntu设置.net core程序开机自启动

在/etc/systemd/system/ 目录下创建.service文件。
UploadServer.service文件:

[Unit]
Description=UploadServer
After=network.target
 
[Service]
WorkingDirectory=/www/wwwroot/db.cnsos.net/UploadServer/UploadServer/bin/Debug/netcoreapp3.1
ExecStart=/usr/bin/dotnet /www/wwwroot/db.cnsos.net/UploadServer/UploadServer/bin/Debug/netcoreapp3.1/UploadServer.dll
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
SyslogIdentifier=UploadServer

[Install]
WantedBy=multi-user.target

3、UploadServer.service无法正常启动

 发现程序在Ubuntu的终端下用dotnet run可以正常启动和运行,但是设置为service以后,就是无法正常使用。

通过下面的命令看了一下:

sudo journalctl -f -u FileServer.service

发现服务在不停地启动和停止。

看了一下代码,Main函数的未尾使用了Console.ReadLine();

换成:

while (true)
{
    Thread.Sleep(1000);
}

应该是service会自动跳过Console.ReadLine(),然后程序就结束了,然后服务本身设置了自动重启,所以不停地停止和重启。

3、Ubuntu系统下路径不正常的问题

 程序在Windows系统下测试良好,但是在Ubuntu系统上却无法正常运行,看了一下,是文件路径的问题。

因为客户端在Windows下运行的,客户端上传的路径里的“\”需要换成“/”。写了一个路径转换函数:

public static string ChangePath(string path)
{
    if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
    {
        path = path.Replace("\\", "/");
        if (path.StartsWith("/"))
            path = path.Substring(1);

        return path;
    }

    if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
    {
        path = path.Replace("/", "\\");
        if (path.StartsWith("\\"))
            path = path.Substring(1);

        return path;
    }

    return path;
}

另外,在使用Path.Combine(path1,path2)进行路径组合的时候,path2不能以"\"或“/”开头,不然的话,路径会组合失败。

3、“Default font family name can't be null or empty.”错误问题

部分Linux操作系统下,能够正常编译,但是无法启动应用,会报“Default font family name can't be null or empty.”的错误。应该是跟字体有关系。网上找了一下资料。可以参照以下网址的方法来尝试解决。

https://www.cnblogs.com/joyandjoys/p/14346935.html

 

4、第三方的MessageBox.Avalonia控件有点问题,会导致应用崩溃退出。

初步判断是因为窗口的图标引起的,而且这个图标不设置也不行。

最新版本已经没有问题。

var msBoxStandardWindow = MessageBox.Avalonia.MessageBoxManager.GetMessageBoxStandardWindow(new MessageBoxStandardParams
{
    ButtonDefinitions = ButtonEnum.Ok,
    ContentTitle = "提示",
    ContentMessage = "请输入网址",
    Icon = Icon.Info,
    Style = Style.UbuntuLinux,
    WindowStartupLocation = WindowStartupLocation.CenterOwner,
    FontFamily = "Microsoft YaHei",
});
await msBoxStandardWindow.Show(App.GetActiveWindow());

不过这个对话框控件容易出现一些问题,类似中文显示乱码等等问题,其实自己写一个简单的对话框窗体也是不错的选择。

 

5、Ubuntu系统下,从IDE上Debug可以正常运行,但是通过系统的桌面图标无法打开。

试了一下,用.desktop里的路径直接在终端里面运行,也是无法正常运行的。在终端上面输出了一些错误信息。看了一下,配置文件的路径,用的是相对路径。

把它改成下面的形式,应用就能正常打开了。

Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Formats/AppConfig")

 

6、在部分机子上,打开OpenFileDialog时,会卡UI,软件无响应。

在Main方法上加上 [STAThread] 的标签。如下所示:

    internal class Program
    {
        // Initialization code. Don't use any Avalonia, third-party APIs or any
        // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
        // yet and stuff might break.
        [STAThread]
        public static void Main(string[] args) => BuildAvaloniaApp()
            .StartWithClassicDesktopLifetime(args);

        // Avalonia configuration, don't remove; also used by visual designer.
        public static AppBuilder BuildAvaloniaApp()
            => AppBuilder.Configure<App>()
                .UsePlatformDetect()
                .LogToTrace();
    }

 

推荐阅读