这是一个当前还没开发完成的功能,准确来说连预览版也算不上的功能。我原本以为 MAUI 是无法在 WPF 上面跑的,然而在看完了 MAUI 整个大的设计,才了解到,原来 MAUI 是一个非常庞大的开发项目。在 MAUI 里面,虽然现在是正式发布的,但正式发布的版本里面只有采用原生控件进行绘制的方案。这和官方开始的宣传不符合,在阅读了 MAUI 相关文档才发现,实际上 MAUI 还有一个很大的部分,那就是自绘部分,还没完成,代码也分了仓库,这就是一开始没找到的原因。本文将告诉大家 MAUI 还没发布的这部分大杀器

本文所涉及的全部都是绘制的渲染层,而众所周知,一个 UI 框架最重要的两个部分就是交互和渲染。本文仅仅只会涉及到渲染的一部分

制作一个跨平台的 UI 框架有很多个方式,例如使用各个平台提供的原生控件,也就是说在 Windows 平台上,采用 WinUI 的按钮,在 iOS 平台上使用苹果提供的按钮,具体的按钮样式等等就需要取平台最小集以及开放定制性,最重要的代表就是原先的 Xamarin 的方式。采用各个平台的提供的原生控件的一个优势在于可以获取平台提供的功能,更加贴合具体平台的视觉和交互,缺点是不同的平台的视觉效果有所差异。另一个方式是做中间较底层的自绘,基本上各个平台都会提供自绘的能力,如 WPF 下的 DrawingContext 和 Win2D 等等,基于此方式做自绘,可以更加方便接入原有的平台,降低原有的应用接入的成本,而这就是本文的重点。最后一个方式是做底层的自绘,使用平台最底层的绘制逻辑,或者其他渲染框架的封装进行二次封装,如 Skia 或 GTK 等,对此进行渲染。使用底层的自绘逻辑可以做到更多的可控性,但缺点也在于可控性导致开发起来十分麻烦,与现有的应用接入也相对来说无法实现最好的性能

很多的 UI 框架都会采用其中的一个方式。然而别忘了 MAUI 是某软主力做的,按照某软的想法,那就是都要。在 MAUI 里面,既可以使用平台提供的原生控件进行拼接制作界面,也可以使用基于的各个平台的独立 UI 框架提供的自绘能力绘制界面,也可以调用到底层的渲染逻辑进行渲染

但,这也不是免费的。如此大的一个项目,自然投入的成本,无论是人力还是开发周期,都是非常庞大的。尽管现在 MAUI 正式发布了,可惜还有很大部分的工作还没完成,甚至还没开始

在吸取了很多次失败的教训之后,某软决定拆分仓库,以解决如此大的一个项目的某些组件或部分的失败带来整体的失败。这是 dotnet runtime 组的成功的例子带来的组织形式的经验,在 dotnet runtime 里面,将不稳定的实验的功能放在 .NET Runtime Lab 仓库里面。不稳定的功能,如果能成,那自然能大大提升 dotnet 的竞争力,如果不成也不应该影响到整个 dotnet 的发布

当前的 MAUI 也是这个管理方式,在 MAUI 里面,将渲染层拆出一个 Microsoft.Maui.Graphics 仓库,如 MAUI 自定义绘图入门 所提到的。其实 Microsoft.Maui.Graphics 是由原本的 System.Graphics 改名而来。这个 System.Graphics 项目初步完成时间比 MAUI 早很多,定位是做全平台的绘制封装层,提供了各个平台的绘制渲染的上层统一。包括了两个实现方式,一个是对各个平台提供的 UI 框架的自绘逻辑进行封装,从而对上层统一。另一个方式对各个底层绘制渲染逻辑包括 Skia 和 GTK 甚至是 DirectX 进行封装,从而提供给上层统一的逻辑,只需要简单的代码即可切换

接下来是在有 Microsoft.Maui.Graphics 的基础上,也就是在能提供各个平台上层统一的绘制能力之后,进行实现各个基础控件。这就是 Microsoft.Maui.Graphics.Controls 仓库,这个仓库的需求就是制作自绘的控件。如此即可实现各个平台上像素级的统一,或者是更加方便接入原有的应用的 UI 框架

本文是在 2022.06 写的,以上的很多功能都只是能吹不能用。但是只是写一篇水文,那可不是我的风格。自然就是开始实际的写代码阶段

认识我的伙伴们都知道,我对渲染是比较熟悉的。我接下来将告诉大家,如何使用 Maui 提供的框架层,配合 WPF 提供具体的自绘逻辑,两个放在一起,从而实现 WPF 使用 MAUI 的自绘逻辑

核心的实现方法是 WPF 提供画布功能,让 MAUI 可以在 WPF 上面画元素。在 MAUI 里面提供框架,以及具体的绘制指导,和上层 API 调用

本文以下部分将用到还没有发布,但是也差不多快完成的 Microsoft.Maui.Graphics.Xaml.WPF 提供的功能。这个库的代码放在 Microsoft.Maui.Graphics 仓库,这个库属于做中间较底层的自绘,利用 WPF 提供的丰富的绘图能力从而介入 MAUI 定义的抽象接口。由于此库还没完成,为了完成接入,我没有使用 DLL 引用,而是拷贝了这个库的代码到我的测试代码里面,然后再进行稍微的魔改,解决构建不通过

大概的对接方式如下,先在 WPF 里面放一个 Canvas 控件,这个控件将被作为 MAUI 的画布。如此也能解答一些伙伴的疑惑,那就是 MAUI 接入 WPF 的话,能作为控件的形式接入,而不作为类似 WindowsFormsHost 的方式接入。如本文下面的代码,只是提供一个 Canvas 控件,让 MAUI 将内容绘制在这个 Canvas 上。如此可见 MAUI 的大的方面的设计还是很好

        <Canvas x:Name="Canvas" />

在后台代码里面,将创建 XamlCanvas 类型的 _canvas 字段,同时将上面代码的 Canvas 传入

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent(); _canvas.Canvas = Canvas; SizeChanged += (source, args) => Draw();
} public IDrawable Drawable
{
get => _drawable;
set
{
_drawable = value;
Draw();
}
} private void Draw()
{
if (_drawable != null)
{
using (_canvas.CreateSession())
{
_drawable.Draw(_canvas, new RectF(0, 0, (float) Canvas.Width, (float) Canvas.Height));
}
}
} private readonly XamlCanvas _canvas = new XamlCanvas();
private IDrawable _drawable;
}

以上代码的 XamlCanvas 继承了 ICanvas 接口。在 MAUI 的自绘里面,最重要的就是 ICanvas 接口,这是一个表示画布的接口,在这个接口里面实现了具体的绘制的抽象 API 定义。换句话说,如果你想要接入自己想要的其他平台,那很重要的一点就是去实现 ICanvas 的功能

以上的 XamlCanvas 是属于库提供的功能,将通过传入的 Canvas 实现对接 MAUI 和 WPF 的逻辑

有了画布之后,想要在界面绘制内容,那还需要告诉框架层想要画出什么内容。这就是属于业务层的内容了,在业务层里面,将需要继承 IDrawable 接口,实现 Draw 方法。在 Draw 方法进行业务层的渲染

例如一个画线的业务功能,可以使用如下实现方式

    class DrawLines : IDrawable
{
public void Draw(ICanvas canvas, RectF dirtyRect)
{
canvas.DrawLine(50, 20.5f, 200, 20.5f); canvas.DrawLine(50, 30.5f, 200, 30.5f);
}
}

将 DrawLines 的对象设置给 Drawable 属性,即可看到界面画出线

以上的 DrawLines 就是属于 通用 MAUI 渲染层 的逻辑,将这段代码拿出来,可以跑在使用其他底层渲染技术但是接入 Microsoft.Maui.Graphics 的渲染技术,例如底层换成是 Win2D 等。如此即可通过造上层的 通用 MAUI 渲染层的逻辑,从而搭建起界面效果的生态。更多自定义的绘图,请看 MAUI 自定义绘图入门 - lindexi - 博客园

我十分推荐大家跑一下我的 demo 从而了解到当前的 MAUI 的实现进度

本文测试代码放在githubgitee 欢迎访问

可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 8d4c37dbbde83e03a6daa4e3454a5d007c64dffe

以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git

获取代码之后,进入 RijoqicainejoHifolurqall 文件夹

WPF 使用 MAUI 的自绘制逻辑的更多相关文章

  1. win10 uwp 通过 Win2d 完全控制笔迹绘制逻辑

    本文来告诉大家如何通过 Win2d 完全控制笔迹绘制逻辑,本文适合用来实现复杂的自定义逻辑,可以完全控制笔迹的行为.包括在书写过程中切换模式,如进行手势擦除切换为橡皮擦模式 本文提供的方法适合用来做复 ...

  2. 在WPF中自定义你的绘制(五)

    原文:在WPF中自定义你的绘制(五) 在WPF中自定义你的绘制(五)                                                                   ...

  3. 在WPF中自定义你的绘制(三)

    原文:在WPF中自定义你的绘制(三) 在WPF中自定义你的绘制(三)                                                                  ...

  4. 在WPF中自定义你的绘制(四)

    原文:在WPF中自定义你的绘制(四)                                   在WPF中自定义你的绘制(四)                                 ...

  5. 在WPF中自定义你的绘制(一)

    原文:在WPF中自定义你的绘制(一)   在WPF中自定义你的绘制(一)                                                                 ...

  6. 在WPF中自定义你的绘制(二)

    原文:在WPF中自定义你的绘制(二)   在WPF中自定义你的绘制(二)                                                                 ...

  7. 理解WPF中的视觉树和逻辑树

    轉載地址:http://blog.csdn.net/changtianshuiyue/article/details/26981797 理解WPF中的视觉树和逻辑树  Understanding th ...

  8. WPF 截图控件之绘制箭头(五)「仿微信」

    前言 接着上周写的截图控件继续更新 绘制箭头. 1.WPF实现截屏「仿微信」 2.WPF 实现截屏控件之移动(二)「仿微信」 3.WPF 截图控件之伸缩(三) 「仿微信」 4.WPF 截图控件之绘制方 ...

  9. WPF 截图控件之绘制方框与椭圆(四) 「仿微信」

    前言 接着上周写的截图控件继续更新 绘制方框与椭圆. 1.WPF实现截屏「仿微信」 2.WPF 实现截屏控件之移动(二)「仿微信」 3.WPF 截图控件之伸缩(三) 「仿微信」 正文 有开发者在B站反 ...

  10. android Animation 动画绘制逻辑

    参考:http://www.jianshu.com/p/3683a69c38ea 1.View.draw(Canvas) 其中步骤为:/* * Draw traversal performs seve ...

随机推荐

  1. LOTO示波器_从零开始手把手测电源开环增益/电源环路频响曲线/PSM

    我们之前有篇文章从理论到实践演示了如何测量电源环路的开环增益曲线,不过偏重于理论和原理,没有很多细节的展现,所以这片文章从另外的角度,从零基础开始,手把手一步一步演示如果进行实操测试. 之前的那篇文章 ...

  2. JSON.stringify() 第三个参数的使用

    语法 JSON.stringify(value[, replacer[, space]]) 参数说明: value: 必需, 要转换的 JavaScript 值(通常为对象或数组). replacer ...

  3. es通过时间聚合查询一周中每天的数据平均值

    场景回顾:设备上传的数据保存在es中,大屏模块要统计本周的数据折线图(一个设备三分总上传一次,所以拟定每天聚合求个平均值) kibana查询请求 GET xxxx_2022-10/_search { ...

  4. 简直了,被“Java并发锁”问题追问到自闭...

    故事 地铁上,小帅双目空洞地望着窗外...绝望,发自内心地感到绝望... 距离失业已经过去两个月了,这是小帅接到的第四次面试邀请."回去等通知吧...",简简单单的六个字,把小帅的 ...

  5. 数据库锁起来了,把事务清掉sql

    select concat('kill ',id,';') from information_schema.`PROCESSLIST` where state !='executing' 将上述代码执 ...

  6. 玩转OpenHarmony PID:教你打造两轮平衡车

    简介 此次为大家带来的是OpenAtom OpenHarmony(以下简称"OpenHarmony")系统与PID控制算法相结合并落地的平衡车项目. PID控制算法是一种经典的,并 ...

  7. 你真会判断DataGuard的延迟吗?

    这是一个比较细节的知识点,但必须要理解这个才能准确判断Oracle ADG的延迟情况. 以前做运维工作时,记得是要同时重点关注v$dataguard_stats视图中的几个字段的值,分别是:NAME. ...

  8. Python-List内部实现

    Python有很大实现的版本,像拿C语言实现的Cpython,以及在其基础上改进其解释执行变为即时编译(jit)的Pypy,还有一些其他的比如Jpython等.具体来说 其中使用c语言开发的叫做pyt ...

  9. 高云GOWIN下载出现No devices found咋办

    在使用GOWIN下载器下载会出现该类问题 No devices found错误. 原因如下: A . Windows10 系统会出现下载器通道顺序错误,所以要确保在 A 通道上. B.有一些 USB ...

  10. SURE:增强不确定性估计的组合拳,快加入到你的训练指南吧 | CVPR 2024

    论文重新审视了深度神经网络中的不确定性估计技术,并整合了一套技术以增强其可靠性.论文的研究表明,多种技术(包括模型正则化.分类器改造和优化策略)的综合应用显着提高了图像分类任务中不确定性预测的准确性 ...