本文记录我将一个小 WPF 应用搬迁到 UNO 框架,用于支持统信 UOS 系统时开发经验
开始之前先说一下我的需求,我现在有一个小的 WPF 应用。现在我需要在统信 UOS 系统和 Windows 系统上都能够运行这个 WPF 应用
众所周知当前的 dotnet 系可选的多平台开发框架有很多,这一次我准备尝试使用 UNO/MAUI 的方式进行开发,大的技术架构如下图
如上图,在 Windows 上依然采用 WPF 框架,只是这时的 WPF 框架是作为底层框架使用,业务代码大部分不会直接接触 WPF 框架,只有部分平台兼容适配代码才会接触 WPF 框架。其他的业务代码都是通过 UNO 和 MAUI 框架间接使用到 WPF 框架。在 UOS 系统上,是采用 GTK 应用框架进行承载,同理也只有平台兼容适配代码才会接触 GTK 应用框架,大部分业务代码不会直接碰到
然后总的渲染层使用 SKIA 来保证多个平台的渲染效果一致
日常开发
新建项目的时候记得勾选 Windows 项目,如此将可以生成 WinUI3 项目。通过编写代码的时候选用 WinUI 3 项目,即可获取 XAML 代码智能提示。调试的时候优先选用 WinUI 3 项目调试界面布局,可以直接使用 Visual Studio 对 WinUI 3 的热重载支持,效果更好
推荐同步也加上 Skia.WPF 和 Skia.GTK 项目,其中 GTK 可以同时在 Windows 和 Linux 系统上跑,但 GTK 在 Windows 上可能有一些奇奇怪怪的问题,此时换成 Skia.WPF 好了,毕竟真的发布在 Windows 平台的也不会那么想不开用 GTK 做底层
当前 UNO 对于 XAML 智能提示,需要切换 XAML 使用 WinUI3 项目的编辑界面,否则将无法显示正确的 XAML 智能提示且出现大量的 XAML 报错。切换 XAML 使用 WinUI3 项目的编辑界面,需要先存在 WinUI3 项目,即在新建项目的时候需要勾选 Windows 项目,然后点击 XAML 选项卡下的项目,切换到 WinUI3 项目,如下图所示
详细请参阅 Intellisense not working, but project compiles · Issue #15517 · unoplatform/uno
构建输出同步
我是在 Windows 设备上进行开发的,在虚拟机里面运行 UOS 系统的。我需要在 Windows 上进行构建,将构建输出的内容在 UOS 系统上运行
我使用的是我所在的团队在 https://github.com/dotnet-campus/dotnetcampus.DotNETBuildSDK 上开源的 SyncTool 工具进行同步
方法是先在 Windows 设备上进行项目的发布,即使用如下命令行进行发布,其中 --self-contained true
是可选的,因为参与开发的 UOS 本身就是安装了全开发包的系统
接着在 Windows 和 UOS 上使用如下命令安装好 SyncTool 工具
定位到 Windows 设备上的发布输出文件夹,使用如下命令行开启文件同步服务,用于将发布输出文件夹提供同步服务,让其他端,即 UOS 系统上可以将发布的文件拉下来
查看以上命令所监听的端口,以及当前 Windows 系统所采用的本地 IP 地址,如有弹出防火墙限制请放行
在 UOS 系统上,进入到一个空闲的文件夹,执行以下命令设置同步
以上命令的 http://123.123.123.123:555
请替换为你在 Windows 系统上运行 SyncTool serve
所监听的端口以及 Windows 系统上所采用的 IP 地址
如此即可完成同步的初始化设置,完成初始化之后,以后的每次发布都会自动同步文件
换句话说,配置完成同步之后,即可在 Windows 端进行发布,然后切换到 UOS 上即可运行发布后的新版本应用。全过程都是自动化的,用起来感觉不错。且在 SyncTool 里面处理了文件占用重试逻辑,整体感觉会更好
文本
在 UOS 闪烁黑屏问题
这是 OpenGL 的问题,修复方法请看
dotnet 在 UOS 统信系统上运行 UNO 程序输入时闪烁黑屏问题
中文文本乱码
中文文本乱码是因为中文字体没有正确加载,在 UOS 默认有思源黑体字体,在 GTK 会自动做字体回滚,只需要应用设置为微软雅黑即可。设置为微软雅黑可以让应用在 Windows 系统和 UOS 系统上都能显示正常的黑体字体
设置方法如下
微软雅黑在界面上记得使用 Microsoft YaHei UI
字体,带 UI
的字体。否则你将会看到一些字体布局有些奇怪
或者是设置全局的文本控件样式,大概的定义如下,以下代码放在 AppResources.xaml 里面,以下是使用 Material 样式时才如此定义。可以看到核心就只是添加了 FontFamily 属性的值
以上代码的 FilledButtonStyle
是 Material 样式系带进来的,详细请参阅 Material Controls Styles
如果不带任何样式,可以使用如下代码
TextBox 撑开空间
如果有内容是依赖 TextBox 的输入过程时的测量撑开的空间的,那撑开的空间将可能不对,比如以下代码
如此的逻辑将会在输入的过程看到文本内容被裁剪,基本在 Skia.WPF 和 Skia.GTK 项目下可以看到文本内容被裁剪
暂时只能绕路,现在是 UNO 5.0 版本,依然难以修复此问题
TextBox 的最小高度
最小高度依然会比预期的更高一些,只能修改界面设计,绕路
TextBox 的滚动条
比如滚动最底,可以使用如下代码
这个 VisualDescendant 方法是辅助方法,代码如下
此方法对于 ListView 等也一样有用。核心就是通过爬视觉树找到 ScrollViewer 对象,通过 ScrollViewer 控制滚动
以上代码注释掉的 textBox.Spy();
是我在调试下输出界面,方便调试是否获取正确滚动条,详细请看 dotnet UNO 如何在调试下输出界面层级结构
几何系列
几何图形 StreamGeometry 资源
在 WPF 里面,经常有图标使用的是 Path 几何路径,作为矢量图标,放入到 StreamGeometry 资源里面。由单个 Path 制作的 StreamGeometry 资源可以通过 x:String
的方式在 UNO 里替换,如下面代码是一个原先放在 WPF 资源里的图标
在 WPF 里面,假定是设置在按钮上,作为图标按钮的,可以定义一个样式,大概内容如下
具体的业务代码使用的代码大概如下
搬运到 UNO 之后,将 StreamGeometry 类型的资源修改为 x:String
资源,如以下代码
其他的代码基本都和 WPF 相同,如下面的 UNO 的按钮样式,可以看到和 WPF 的相同。实际应用里面,可能需要去掉一些 WPF 专有的属性,比如 FocusVisualStyle 属性,以及为了界面效果更好添加一些 UNO 的属性
具体的业务使用方代码不变,以下是 UNO 的按钮,可以看到和 WPF 的按钮的代码是相同的
PathGeometry
有部分不受支持,请进行多平台测试,需要绕路
GeometryDrawing
绕路,请使用多个 Path 界面控件代替,一般代替方法为创建一个 Canvas 容器,在容器里面存放多个 Shape 元素,从而实现类似与 GeometryDrawing 的效果。所添加的 Canvas 容器记得设置正确的尺寸,防止裁剪或界面看不见
Geometry.Parse
从字符串创建出 Geometry 的 Geometry.Parse("M0,0L1,1")
等类似的转换代码为无法在后台代码实现,推荐在 XAML 里面,使用 Path 和 Data 属性进行代替
在 UWP 和 WinUI3 以及 UNO 上,没有直接提供从 SVG Path (mini-lang) 转换为 Geometry 的方法,唯一的转换就是通过 XAML 设置 Path 的 Data 的方式
强行后台代码转换的方式如下
详细请参阅 c# - Convert path to geometric shape - Stack Overflow
可能存在 FillRule 为 EvenOdd 和 Nonzero 的不同行为差异,此差异性问题已经被我在 fix(Skia): Fix ineffective FillRule setting for StreamGeometry by lindexi · Pull Request #15888 · unoplatform/uno 修复,预期后续版本不会遇到此问题
XAML 系列
x
静态绑定不受支持,只能绕路,比如使用再定义一个实例属性,让这个实例属性引用静态量,再绑定到实例属性
或者是有一些从静态属性搬到资源字典
比如原本在 WPF 是这样写的
在 UNO 更改使用资源字典
design 设计时
设计时可正常使用,推荐给 Page 等 XAML 的 UI 界面搭配上 d:DataContext
使用,此时切换到 WinUI 3 框架时,可以让 ReSharper 和 VisualStudio 开森,可以在绑定时提供智能提示
但如果写了 d:DataContext
时提示 WMC0011 错误,错误信息如下时,则可能忘记将 d:
命名空间加入忽略
XamlCompiler error WMC0011: Unknown member ‘DataContext’ on element ‘Page’
以上错误的原因是没有将 d:
命名空间加入到 mc:Ignorable
列表里面,导致存在不认识的命名空间而失败。修复方法是将 d:
加入忽略列表,如以下代码
以上代码要求在 xaml 里面已经添加 mc 命名空间,如以下代码
加上之后的代码如下
以上这部分代码和 WPF 相同,直接抄即可
类型是自定义控件类型将构建失败
非必现问题,复现步骤:
- 创建一个自定义控件,无 XAML 类型,仅类型定义,比如
public partial class Foo : ContentControl
的方式的定义 - 创建一个带 XAML 的自定义控件,将其基础类型更改为 Foo 类型
构建可能提示如下错误,且在 Skia.WPF
和 Skia.Gtk
项目能够构建通过
Fx.xaml(1,2): XamlCompiler error WMC0001: Unknown type ‘Foo’ in XML namespace ‘clr-namespace
;assembly=LindexiDemo, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null’遇到此错误只能绕路,去掉控件之间的继承
此问题可能换成新的 <Project Sdk="Uno.Sdk">
可以修复,但是由于非必现问题,我暂时没有复现步骤
命名空间引用错误
这个常见于拷贝代码过程中,即在 WPF 这边的 xmlns:foo="clr-namespace:Xxxxx
中的 clr-namespace
应该是被替换为 using
才对。此类问题在于会在 XAML 代码里面发现明明类型能够找到,但是构建过程中却报错说找不到类型,如更明确的 XamlCompiler error WMC0909: Cannot resolve DataType foo:Xxxxx
错误
以下代码是错误的:
以下代码是正确的:
除了拷贝代码可能的出错,也有可能是 ReSharper 在修改类型的命名空间的时候,自动向 XAML 添加的代码错误
常见错误信息如下
图片资源
图片资源可以使用相对路径或绝对路径,在UNO的绝对路径的格式如下
以上代码的 [MyApp]
是可选的,但是我推荐加上,这个 [MyApp]
对应的是程序集名
默认的图片都是被作为 Content
引用的,可以在 csproj 项目文件看到如下代码
新添加的图片文件,默认是不需要做什么修改的,但为了兼容平台考虑,推荐使用 png 和 jpg 和 bmp 格式,这几个格式所有平台都支持。如果发现自己的图片没有显示,请按照如下顺序定位
- 先看看是否改了 csproj 将自己的图片忽略掉
- 尝试写资源使用绝对路径
- 逐字符对比绝对路径是否正确
- 逐字符对比是否写的是
ms-appx:///
字符串开始,需要使用的是三个/
字符 - 如果依然看不到图片,再看看是不是没有生成试试重新生成
- 依然不行再看看是不是图片格式比较诡异,比如将 webp 图片后缀名改为 png 等
图片当成资源字典的内容,可以使用 BitmapImage 类型,和 WPF 相同,只是 Source 的内容在绝对路径下需要更改,如以下例子
更多请参阅官方文档 Assets and image display
ContentControl
功能上和 WPF 对齐,只是样式默认行为不相同。默认的 HorizontalContentAlignment 和 VerticalContentAlignment 是左上角,需要设置为 Stretch 才和 WPF 相同
我编写了一个 ContentControl 示例代码,演示使用 ContentControl 移动一个橡皮擦界面样式的元素,代码放在 github 和 gitee 上,可以使用如下命令行拉取代码
先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码
以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源。请在命令行继续输入以下代码,将 gitee 源换成 github 源进行拉取代码
获取代码之后,进入 RalllawfairlekolairHemyiqearkice 文件夹,即可获取到源代码
布局
Panel.ZIndex
将 WPF 的 Panel.ZIndex 替换为 Canvas.ZIndex 即可,此 Canvas.ZIndex 可以用在 Grid 等等控件上。我感觉是 WinUI3 的不良设计,不应该将此附加属性放在 Canvas 上
效果如下
可以看到尽管放在 Grid 里面,红色的 Border 可以显示到黑色的 Border 之上,证明 Canvas.ZIndex 可以作用到 Grid 控件里
后台代码可以使用 Canvas.SetZIndex(Border, 1)
静态方法进行设置,等价于 XAML 的 Canvas.ZIndex="1"
代码
窗口
不同于 WPF 的窗口化,为了更好的跨平台,推荐只做单个窗口然后在窗口里面进行页面切换逻辑。推荐修改 UI 交互方式
窗口标题
和 WPF 相同,只需设置 Title 属性即可
以上的 IStringLocalizer 仅仅只是为了做多语言而言,可以执行更改多语言策略
控件默认属性
大部分的控件的默认属性都和 WPF 相同,但也有少部分布局属性和 WPF 不相同,比如大量控件的 HorizontalAlignment 和 VerticalAlignment 都是左上角,需要设置为 Stretch 才和 WPF 相同
csproj 的变更
由于现在 UNO 和 VisualStduio 存在一些冲突,导致了新建文件可能让 UNO 的 csproj 添加了不需要的代码。需要在开发的过程中,在进行 git 上传之前,看一下 csproj 的变更是否必要,如果是不必要的改动,请直接撤销。一般需要在新建文件,比如新建类型或新建用户控件这些动作之后,撤销 csproj 的更改
Dispatcher
调度上 UNO 的 Dispatcher 要比 WPF 的弱,但可以进行一些平替。从原本的界面元素上获取 Dispatcher 的逻辑,依然不变
从静态获取的逻辑,如以下的 WPF 代码,则需要进行替换
从 UNO 获取静态的主线程调度器和 UWP 或 WinUI 3 的获取方法是相同的,代码如下
和 WPF 的 Dispatcher 调度等级不相同的是 UNO 的可调度等级非常少,只有如下的可调度等级
大部分情况下使用的都是 Normal 优先级
但是在 WinUI 3 运行的时候,可能 CoreApplication.MainView.CoreWindow
属性的获取会抛出不能重复创建的异常。而如果尝试通过 CoreApplication.GetCurrentView()
获取 CoreApplicationView 类型的对象从而间接拿到 Dispatcher 则依然可能失败,因为此方法将会抛出 System.Runtime.InteropServices.COMException:“Element not found” 异常
比较稳妥的方式就是自己在 App 里面将 Microsoft.UI.Dispatching.DispatcherQueue 存起来,如此获取到相同的从主 UI 线程获取的 DispatcherQueue 对象即可同时在 WinUI 3 以及 WPF 和 GTK 项目上使用。在 WinUI 3 项目里 MainWindow.Dispatcher 属性当前依然是 null 值,这就是为什么拿的是 DispatcherQueue 的原因
或者是执行依赖注入方式,如下面代码定义
在 ConfigureServices 里面进行注入,注入时写的就是 MainWindow.DispatcherQueue 属性,如下面代码
以上的 ConfigureServices 是写在默认项目的 App.cs 代码里面,如此即可让 ViewModel 层使用 IDispatcherQueueProvider 进行 UI 调度。详细更改请参阅 https://github.com/dotnet-campus/dotnetCampus.FileDownloader/commit/2fc43a8050741564cdb4810266bc912149ca318f
多语言
在 Resources.resw 里面不能使用 /
标识,否则将会遇到如下错误
也就是如以下代码是不能作为多语言的标识的
可选修复方法是将 /
替换成 _
或 .
字符,如下面代码
然后在 Resources.resw 里面使用如下记录
但推荐尽量使用 _
下划线,下划线的兼容性更好一些。防止中间下划线被有时识别为属性名,导致找不到多语言,如以下官方文档
The x
is used for localization. To localize a property, you need to add a string resource in each resource file using its x followed by a dot (.) and then the property name. eg:MainPage_IntroText.Text
More on this in the resource steps that follow.
在 UNO 里面,将会构建 resw 为 upri 中间文件
暂时在 WinUI3 项目上的多语言切换可能一直都会使用英文,无法正确识别到中文,但是 GTK 和 WPF 项目都没有此问题
缺乏的机制
Visibility.Hidden
没有隐藏的选项,换成设置透明度为 0 代替。设置 Opacity="0"
效果和 WPF 的 Visibility.Hidden
相似
MultiBinding
多绑定不受支持,只能绕路,让界面编写只有单绑定
ControlTemplate.Triggers
不支持,需要绕路
在 Resources 的资源使用了 x 特性
在资源里面带了 x
是不受支持的,由于 x 在生成的时候必须分配给他属性或字段,但是资源可以被多次创建,导致了生成的代码无法处理这个情况。之前 Avalonia 的 XAML 创建器就提了这个问题,现在 WinUI 3 和 UNO 和 MAUI 都有这个问题最简复现代码如下
此时应该是使用 x:Key
代替 x:Name
才符合预期
另外的是为了资源内的绑定逻辑,如以下代码,这样的代码只能绕路
以上代码错误提示是 error CS0103: 当前上下文中不存在名称“_RootGrid”
信息
更多请看 Adding Name to a Resource fails on build · Issue #1427 · unoplatform/uno
设计时资源引用
似乎玩不出来让 VisualStudio 和 ReSharper 开森的方式
IsEnable 为 false 下的界面闪烁现象
新建一个文本,应用 Material 样式,如下面代码设置 IsEnable 为 false 值,切换到 Skia.WPF 平台运行
或者是将 Button 放入到 ListView 的 ItemTemplate 里面,如此运行项目也许可以看到界面正在闪烁
在 UIElement 的属性上标记 Obsolete 且为 true 导致构建失败
任何直接或间接继承自 UIElement 的类型的属性,都不能标记 Obsolete 且为 true 否则将会导致 XamlTypeInfo.g.cs 生成代码构建失败
因为在 XamlTypeInfo.g.cs 生成的代码将会访问所有的 UI 元素的属性。如果有某个属性标记为 Obsolete 且为 true 将会导致构建失败
在 MVU 下带 out 方法将导致构建不通过
如以下代码将导致构建不通过
原因是源代码生成没有处理方法带 out 的
可以在方法上添加 [Uno.Extensions.Reactive.Commands.Command(false)]
特性让源代码生成不要处理此方法
Geometry.Empty 属性不支持
绕路
ScaleTransform 不包含采用 2 个参数的构造函数
以下代码将会构建不通过,原因是不再提供构造函数赋值
解决方法:给属性赋值代替即可
使用 TypeDescriptor.GetConverter 转换颜色
如以下代码将会转换失败
异常信息是 System.NotSupportedException:“TypeConverter cannot convert from System.String.”
解决方法:参考 win10 uwp 颜色转换
文件系统
所有路径都是采用 /
作为分割而不是采用 \
作为分割,必须小心各种拼接路径的写法。最好是使用 Path.Combine
或 Path.Join
方法辅助拼接路径,尽量不要自己使用分隔符拼接字符串
在 Linux 系统上,没有盘符的概念,请不要认为 C:
是根路径
IPC
已知问题:
Linux 下的 Console.Read 将导致管道无法读取到消息 · Issue #139 · dotnet-campus/dotnetCampus.Ipc
Environment.GetFolderPath 行为
原本写的 ApplicationData 的逻辑或使用 LocalApplicationData 都需要做一定的变更。继续将应用数据放在 LocalApplicationData 依然是正确的。这部分在我的应用里面不用做什么变更
参阅 dotnet 测试在 Linux 系统上的 Environment.GetFolderPath 行为
启动应用或打开文件的替代
在原本 Windows 下的使用 explorer 打开文件或文件夹的大概如下代码,需要进行替换,因为 Linux 上没有 explorer 应用
可以替换为设置 ProcessStartInfo 的 UseShellExecute 为 true 进行打开文件或文件夹,或采用 xdg-open 代替 explorer 的部分功能。请参阅 dotnet 测试在 UOS Linux 上使用 Process Start 打开文件的行为
安装包
请参阅:
构建已知问题
Debug.Assert 之类的代码构建不通过
在任何的 UIElement 或其继承类里面编写任何 Debug.*
的代码都将在 android 平台构建不通过,提示错误如下
原因是 UIElement 在安卓平台将会继承 Android.Views.ViewGroup 类型,在 Android.Views.ViewGroup 类型里面包含名为 Debug()
的方法,从而导致了 Debug.Assert
方法的 Debug 静态类与 Debug()
方法冲突
解决方法,写全命名空间 System.Diagnostics.Debug.*
即可,如 System.Diagnostics.Debug.Assert
或 System.Diagnostics.Debug.WriteLine
等类似的代码
还原 NuGet 程序包时出错 还原输入无效 原始目标框架值必须与别名匹配
如遇到以下错误信息
可以考虑修改 TargetFrameworks 内容进行处理,这在使用 5.1 版本 Uno.Sdk 更新旧项目时,可能会遇到的问题。更改例子如我在 github 上的 https://github.com/lindexi/lindexi_gd/commit/d49ee7ce3f60c139076aa5cf21d88f0c305bf761 更改内容
代码更改不生效
可能是 VisualStudio 增量构建的锅,记得打上断点,通过断点是否红点判断代码是否最新。如果提示白点或在断点添加感叹号说明构建没有使用到新的代码
Xaml Internal Error error WMC9999
如遇到以下错误提示,可能是将 win 平台加入 mc:Ignorable
列表导致的构建失败,详细请参阅 UNO WinUI 已知问题 在 XAML 条件构建里将 win 平台加入 Ignorable 将构建失败
简单的复现代码如下
核心错误代码是 mc:Ignorable="d win not_win"
将 win 平台加入忽略列表
解决方法就是将 win 平台从 mc:Ignorable
里删掉,更正后的代码是 mc:Ignorable="d not_win"
这么写的
这是 WinUI 平台的问题,即使新建一个非 UNO 的纯 WinUI 3 项目也能复现此问题
找不到 Uno.Sdk 错误
可能是缺少 nuget.config 导致默认配置没有官方 NuGet 源,导致拉取不到库,提示以下错误
修复方法是添加 nuget.config
文件到 sln 文件同文件夹下,在 nuget.config 里面存放以下代码。如果当前项目不缺少 nuget.config 文件,则请尝试替换 nuget.config 为以下代码试试能够解决 Uno.Sdk 找不到的问题,从而确定是否当前项目的 nuget.config 文件存在编写错误
另一个可能错误点是缺少 global.json 文件或 global.json 里面没有定义 Uno.Sdk 的版本。可以尝试新建或替换 global.json 为如下代码,新建的 global.json 也同样需要放在 sln 文件所在的文件夹里面
如果以上的 global.json 定义的版本号错误,也可能导致 UNOB0004: The $(UnoVersion)
property must match the version of the Uno.Sdk defined in global.json 错误。修复方法同上。详细请参阅 How to upgrade Uno Platform NuGet Packages
已知问题
调用 SKXamlCanvas 的 Invalidate 没有触发 PaintSurface 事件
原因是 SKXamlCanvas 没有尺寸
可以尝试看看 SKXamlCanvas 的尺寸
此问题我报告给官方,请看: https://github.com/unoplatform/uno/issues/17326
无法在 Loaded 事件之后立刻获取到正确的 ActualWidth 和 ActualHeight 的值
如下代码将会输出 Width=0 Height=0
的值
此问题已经报告给官方: https://github.com/unoplatform/uno/issues/17243
此问题已在 5.4.0-dev.51
版本修复
无法在 BitmapImage 的 ImageOpened 获取图片解码尺寸
如以下代码,是无法获取到图片解码尺寸
所有输出的 DecodePixelWidth 和 DecodePixelHeight 都是没有值
此问题已经报告给官方: https://github.com/unoplatform/uno/issues/17285
此问题在报告给官方之后,只用 10 个小时就被修复了
参考文档
dotnet 在 UOS 国产系统上使用 Xamarin Forms 创建 xaml 界面的 GTK 应用
dotnet 使用 Avalonia 开发 UOS 原生应用
dotnet 在国产 UOS 系统利用 dotnet tool 工具做文件传输
在 UOS 统信运行 dotnet 程序提示没有通过系统安全验证无法运行
dotnet 在 UOS 统信系统上运行 UNO 程序输入时闪烁黑屏问题
dotnet 统信 UOS 运行 UNO FrameBuffer 应用错误 Failed to open FrameBuffer device
dotnet 统信 UOS 运行 UNO FrameBuffer 应用错误 Failed to open FrameBuffer device
从 Uno Platform 4 更新 Uno Platform 5 的迁移方法 腾讯云
UNO 新建基础库项目构建提示 UNOB0002 错误 腾讯云
UNO 已知问题 在后台线程触发 SKXamlCanvas 的 Invalidate 且在 PaintSurface 事件抛出异常将炸掉应用 腾讯云
UNO WinUI 已知问题 在 XAML 条件构建里将 win 平台加入 Ignorable 将构建失败
UWP WinUI3 传入 AddHandler 的 RoutedEventHandler 类型与事件所需不匹配将抛出参数异常
中文视频教程 I share a video of an app which created with uno · unoplatform/uno · Discussion #4962
VisualStudio 如何 SSH 远程调试 Linux 的 dotnet 应用的启动
开发社区
如有 UNO 开发过程相关问题,欢迎加入 724181515 QQ群讨论
如有国产系统开发的相关问题,欢迎加入 810052083 QQ群讨论
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。 欢迎转载、使用、重新发布,但务必保留文章署名 林德熙 (包含链接: https://blog.lindexi.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我 联系。