专栏首页林德熙的博客WPF 使用 MAUI 的自绘制逻辑

WPF 使用 MAUI 的自绘制逻辑

这是一个当前还没开发完成的功能,准确来说连预览版也算不上的功能。我原本以为 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 文件夹

本文参与 腾讯云自媒体分享计划 ,欢迎热爱写作的你一起参与!
本文分享自作者个人站点/博客:https://blog.lindexi.com/复制
如有侵权,请联系 cloudcommunity@tencent.com 删除。
登录 后参与评论
0 条评论

相关文章

  • MAUI 自定义绘图入门

    在2022的5月份,某软正式发布了 MAUI 跨平台 UI 框架。我本来想着趁六一儿童节放假来写几篇关于 MAUI 入门的博客,可惜发现我不擅长写很入门的博客。...

    林德熙
  • 【愚公系列】2022年09月 MAUI框架-MAUI项目的创建

    在2020年5月, 微软宣布了MAUI跨平台框架, MAUI 是Xamarin.Forms演变而来, 这也就意味着, 如果你原来具备Xamarin.Forms开...

    愚公搬代码
  • 分享这位大神的WPF界面设计系列视频

    今天介绍油管上一个大佬发的WPF设计系列视频,每个视频都没有旁白,只有背景音乐和大佬敲码的过程。

    沙漠尽头的狼
  • .NET Core/.NET5/.NET6 开源项目汇总9:客户端跨平台UI框架

    .NET Core 实现了跨平台,支持在 Windwos、Linux、macOS上开发与部署,但是也仅限于Web应用程序。对于Windows桌面端应用程序,Wi...

    张传宁IT讲堂
  • SkiaSharp 渲染输出 SVG 文件

    谷歌的 Skia 的一个卖点就是提供了完美的 SVG 的支持,包括输入和输出。输入指的是给一张 SVG 图片,将这个 SVG 渲染出来。输出就是将输出画面保存为...

    林德熙
  • Xamarin.Form 5.0: 新功能和控件以及调试改进

    上周在.NET Conf 2020,Scott Hunter(.NET),Maddy Leger(微软移动开发工具-Xamarin项目经理)和David Ort...

    张善友
  • WinUI 3 试玩报告

    在微软 Build 2020 开发者大会上,WinUI 团队宣布可公开预览的 WinUI 3 Preview 1,它让开发人员可以在 Win32 中使用 Win...

    dino.c
  • .NET 6 预览版发布,Python的跨平台地位受到挑战

    跨平台是最近几年非常火的主题,因为现在的各种平台简直太多了。Windows、macOS、Linux、Android、iOS、Web、小程序、IoT等等。以后还可...

    蒙娜丽宁
  • Xamarin 社区工具包的现状和未来

    Xamarin 社区工具包是一个使用 Xamarin.Forms 进行移动开发的可重用的元素集,包括动画、行为、转换器、效果和辅助工具。它简化了在使用 Xama...

    深度学习与Python
  • 在Entity Framework中使用存储过程(三):逻辑删除的实现与自增长列值返回

    本篇文章通过实例的方式,讨论两个在EF使用存储过程的主题:如何通过实体和存储过程的映射实现逻辑删除;对于具有自增长类型主键的数据表,在进行添加操作的时候如何将正...

    蒋金楠
  • WPF 底层 从手指触摸屏幕到笔迹在屏幕显示中间的步骤

    整个 WPF 就是一个UI框架,一个 UI 框架最重要的是 交互 和 显示 部分,而书写这个功能将会完全贯穿 WPF 整个框架的功能。本文非入门级博客,本文包含...

    林德熙
  • 【转】使用DirectUI技术实现QQ界面

    landv
  • 再见Xamarin,微软官宣跨平台 UI 框架 MAUI

    Build 2020 大会上,微软终于正式公布 .NET 上的跨平台框架,正式版将在 .NET 6 和大家见面。

    Enjoy233
  • [翻译] .NET 官宣跨平台 UI 框架 MAUI

    Build 2020 大会上,微软终于正式公布 .NET 上的跨平台框架,正式版将在 .NET 6 和大家见面。

    Jlion
  • 【Telerik和Kendo UI组件】上海道宁与progress为您提供Web、移动和桌面构建功能更丰富的现代体验

    Progress是已经成立40多年的科技公司,是一家经验丰富、值得信赖的产品供应商。

    51Component
  • WPF架构学习总结

    预期读者     1. 初学者。     2. 懒得总结的人。:)     3. 想大致了解WPF框架主要类的功能的人。 前言     学习WPF也有段时间了,...

    用户1172223
  • WPF SharpDx 性能优化方法

    监听了 Window 的 ContentRendered 事件将会降低整个 WPF 的渲染性能

    林德熙
  • WPF 自己封装 Skia 差量绘制控件

    使用 Skia 能做到在多个不同的平台使用相同的一套 API 绘制出相同界面效果的图片,可以将图片绘制到应用程序的渲染显示里面。在 WPF 中最稳的方法就是通过...

    林德熙
  • 浅谈Xamarin Community Toolkit的未来发展

    .NET MAUI会在今年晚些时候发布,我们也很高兴和大家一起分享我们对Xamarin Community Toolkit的计划! 这包括 .NET MAUI ...

    沙漠尽头的狼

扫码关注腾讯云开发者

领取腾讯云代金券