MAUI与Blazor共享一套UI,媲美Flutter,实现Windows、macOS、Android、iOS、Web通用UI

1. 前言

距离上次发《MAUI初体验:爽》一文已经过去2个月了,本计划是下半年或者明年再研究MAUI的,现在计划提前啦,因为我觉得MAUI Blazor挺有意思的:在Android、iOS、macOS、Windows之间共享UI,一处UI增加或者修改,就能得到一致的UI体验。

看看这篇文章《Blazor Hybrid/MAUI 简介和实战[1]》对MAUI Blazor的说明:

MAUI

.NET 多平台应用程序 UI (.NET MAUI) 是一个跨平台框架,用于使用 C# 和 XAML 创建本机移动和桌面应用程序, 使用 .net MAUI,可以开发可在 Android、iOS、macOS 上运行的应用,Windows 以及从单个共享代码库运行的应用。

Blazor Hybrid 应用和 .NET MAUI

Blazor Hybrid 支持内置于 .NET 多平台应用 UI (.NET MAUI) 框架。.NET MAUI 包含 BlazorWebView 控件,该控件运行将 Razor 组件呈现到嵌入式 Web View 中。通过结合使用 .NET MAUI 和 Blazor,可以跨移动设备、桌面设备和 Web 重复使用一组 Web UI 组件。

今天就分享如何在Blazor Server、Blazor Wasm、MAUI Blazor之间共享UI的实验,这一步完成,后面开发应用时就方便多了(只针对UI修改)。

2. 先来体验下各端最终效果

  • Blazor Server:http://server.dotnet9.com/

  • Blazor Wasm:http://wasm.dotnet9.com/

  • MAUI(Android\Windows\macOS):https://github.com/dotnet9/Dotnet9/tree/develop/src/Dotnet9.MAUI(源码自行编译)

Windows桌面、Blazor Server(在线)、Blazor Wasm(在线)、Android效果

cbaebfbb91876a681f08f22372ac0c57.gif

iOS、macOS桌面效果

12303d8f326c18bbb313ed8cecece356.png

MAUI各端未做发布文件体验(需要做相应平台的发布签名等操作),大家可以按下面介绍的方法创建项目编译体验一下。

iOS和macOS效果感谢青城同学[2]提供的图片素材,站长mbp安装了最新的macOS,xCode也是最新的,可能因为预览版macOS原因,xCode无法打开,间接影响了maui编译?

f37d0482fec644c0d57d74c3cc118760.png

3. 新建项目

关于MAUI的环境搭建可参考这篇文章《在MAUI中使用Masa Blazor》,本文不再介绍环境搭建,直接使用VS 2022最新预览版项目模板创建项目。

3.1 创建Blazor Server项目:Dotnet9.Server

a85a5b682b1f07445da2ff7dba4cb6d8.png

3.2 创建Blazor WebAssembly项目:Dotnet9.Wasm

a91d961c5835607a6ed9f8a1731d202b.png

3.3 创建MAUI Blazor项目:Dotnet9.MAUI

0fd4985f12ecea54296e1ede0954b35b.png

3.4 查找共同点

在3个项目的上一层目录,打开PowerShell,输入tree /f查看详细的目录文件组织结构:

d9586ef55a357ae78c121286bf0414bc.gif

仔细查看三个模板项目文件结构,我们找出共同的文件查看:

文件夹 PATH 列表
卷序列号为 76F5-AF62
C:.
│  Dotnet9.sln
│
├─Dotnet9.MAUI
【1 这里省略数个文件】
│  │
│  ├─Data
│  │      WeatherForecast.cs
│  │      WeatherForecastService.cs
│  │
│  ├─Pages
│  │      Counter.razor
│  │      FetchData.razor
│  │      Index.razor
【2 这里省略数个文件】
│  │
│  ├─Shared
│  │      MainLayout.razor
│  │      MainLayout.razor.css
│  │      NavMenu.razor
│  │      NavMenu.razor.css
│  │      SurveyPrompt.razor
【3 这里省略数个文件】
│
├─Dotnet9.Server
│  │  App.razor
【4 这里省略数个文件】
│  │
│  ├─Data
│  │      WeatherForecast.cs
│  │      WeatherForecastService.cs
│  │
│  ├─Pages
│  │      Counter.razor
│  │      Error.cshtml
│  │      Error.cshtml.cs
│  │      FetchData.razor
│  │      Index.razor
│  │      _Host.cshtml
│  │      _Layout.cshtml
│  │
│  ├─Properties
│  │      launchSettings.json
│  │
│  ├─Shared
│  │      MainLayout.razor
│  │      MainLayout.razor.css
│  │      NavMenu.razor
│  │      NavMenu.razor.css
│  │      SurveyPrompt.razor
【5 这里省略数个文件】
│
└─Dotnet9.Wasm
【6 这里省略数个文件】│├─Pages│      Counter.razor│      FetchData.razor│      Index.razor│├─Properties│      launchSettings.json│├─Shared│      MainLayout.razor│      MainLayout.razor.css│      NavMenu.razor│      NavMenu.razor.css│      SurveyPrompt.razor
【7 这里省略数个文件】

发现都有Data目录和Pages目录(其中Wasm项目没有Data目录,使用的示例类是直接写在FetchData.razor文件@code{}中的),那把这部分文件直接提取到类库中就可以了,那就做吧。

4. 提取UI到Razor类库

创建Razor类库:Dotnet9.WebApp

5771f4f1ce243638a12c8503bcb6a728.png

下面开始UI的提取

5839a63dd4e748807d00b4b0b03fd145.png

如上图,将Dotnet9.MAUI项目的DataPagesShared三个目录外加Main.razor文件剪切到Dotnet9.WebApp项目中,然后修改剪切后相应文件的命名空间Dotnet9.MAUI[xxx]Dotnet9.WebApp[xxx],打开Dotnet9.WebApp项目的_Import.razor文件,参考Dotnet9.MAUI项目的_Import.razor文件部分命名空间,修改如下:

@using System.Net.Http
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using Dotnet9.WebApp
@using Dotnet9.WebApp.Shared

上面部分命名空间可以删除(未尝试),编译Dotnet9.WebApp项目,检查是否正确编译。

5. 各端项目修改

5.1 MAUI项目

  1. 添加Dotnet9.WebApp项目引用

  2. Program.csusing Dotnet9.MAUI.Data;改为using Dotnet9.WebApp.Data

  3. 删除DataPagesShared三个目录外加Main.razor文件,上一步是剪切的话这步省略

  4. 修改_Imports.razor文件,主要是添加Dotnet9.WebApp项目命名空间引用

@using System.Net.Http
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using Dotnet9.MAUI
@using Dotnet9.WebApp
@using Dotnet9.WebApp.Shared
  1. MauiProgram.cs修改引用的命名空间:using Dotnet9.MAUI.Data; => using Dotnet9.WebApp.Data;

  2. 打开MainPage.xaml,对路由组件命名空间的引用修改

添加命名空间xmlns:webApp="clr-namespace:Dotnet9.WebApp;assembly=Dotnet9.WebApp",修改代码如下:

修改前:

<RootComponent Selector="#app" ComponentType="{x:Type local:Main}" />

修改后:

<RootComponent Selector="#app" ComponentType="{x:Type webApp:Main}" />

修改完毕,编译运行Dotnet9.MAUI项目吧,接下来修改Dotnet9.Server项目。

5.2 Blazor Server项目

  1. 添加Dotnet9.WebApp项目引用

  2. Program.csusing Dotnet9.Server.Data;改为using Dotnet9.WebApp.Data;

  3. 删除Data目录

  4. 删除Pages目录中的Counter.razorFetchData.razorIndex.razor三个文件(包括同名的.cs.css文件)

  5. 删除Shared目录

  6. 修改_Imports.razor文件,主要是添加Dotnet9.WebApp项目命名空间引用

@using System.Net.Http
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using Dotnet9.Server
@using Dotnet9.WebApp
@using Dotnet9.WebApp.Shared
  1. 打开./Pages/_Host.cshtml文件,添加命名空间引用@using Dotnet9.WebApp,修改代码如下:

修改前:

<component type="typeof(App)" render-mode="ServerPrerendered" />

修改后:

<component type="typeof(Main)" render-mode="ServerPrerendered" />

修改完毕,编译运行Dotnet9.Server项目吧,接下来修改Dotnet9.Wasm项目。

5.3 Blazor Wasm项目

  1. 添加Dotnet9.WebApp项目引用

  2. 删除PagesShared目录外加App.razor文件

  3. Program.csusing Dotnet9.Wasm;改为using Dotnet9.WebApp;,同时修改代码

修改前

builder.RootComponents.Add<App>("#app");

修改后

builder.RootComponents.Add<Main>("#app");
  1. 修改_Imports.razor文件,主要是添加Dotnet9.WebApp项目命名空间引用

@using System.Net.Http
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using Dotnet9.Server
@using Dotnet9.WebApp
@using Dotnet9.WebApp.Shared

修改完毕,编译运行Dotnet9.Wasm项目,至此三种项目模板已经修改完成,最终解决方案如下图:

f229cb995649e05c6bc3e12f1f367f94.png

6 总结

总结就是下图:

7cfb94053f52bb951d61a5d67b5554f7.png
  • Dotnet9.WebApp:blazor组件相关的代码、路由组件等放在这个工程,供其他项目引用

  • Dotnet9.Server:Blazor Server模板项目

  • Dotnet9.Wasm:Blazor WebAssembly项目

  • Dotnet9.MAUI:MAUI Blazor项目

一句话:将UI封装到Razor类库Dotnet9.WebApp,其他终端工程(Dotnet9.ServerDotnet9.MAUIDotnet9.Wasm)引用此工程即可实现UI共享。

  • 本文代码地址:https://github.com/dotnet9/Dotnet9[3]

  • 原文:https://dotnet9.com/2022/06/Share-razor-library-between-maui-and-blazor-server-or-client[4]

参考

  1. ASP.NET Community Standup - Native client apps with Blazor Hybrid[5]

  2. Blazor一份代码在Blazor WebAssembly和Blazor Server之间任意切换[6]

  3. 微软MAUI文档[7]

  4. 微软Blazor文档[8]

  5. 学Blazor[9]

参考资料

[1]

Blazor Hybrid/MAUI 简介和实战: https://www.cnblogs.com/densen2014/p/16240966.html

[2]

青城同学: https://iwscl.com/

[3]

https://github.com/dotnet9/Dotnet9: https://github.com/dotnet9/Dotnet9

[4]

https://dotnet9.com/2022/06/Share-razor-library-between-maui-and-blazor-server-or-client: https://dotnet9.com/2022/06/Share-razor-library-between-maui-and-blazor-server-or-client

[5]

ASP.NET Community Standup - Native client apps with Blazor Hybrid: https://www.youtube.com/watch?v=7UM6s0QPvRQ

[6]

Blazor一份代码在Blazor WebAssembly和Blazor Server之间任意切换: https://www.bilibili.com/video/BV1ty4y137yA?spm_id_from=333.337.search-card.all.click&vd_source=fc9bd0ca1f113a165ad3ebf4fb79b124

[7]

微软MAUI文档: https://docs.microsoft.com/zh-cn/dotnet/maui/?WT.mc_id=dotnet-35129-website

[8]

微软Blazor文档: https://docs.microsoft.com/zh-cn/aspnet/core/blazor/?WT.mc_id=dotnet-35129-website&view=aspnetcore-6.0

[9]

学Blazor: https://dotnet9.com/album/Let-us-learn-blazor-together

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/285734.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

dns 报文格式

最近学习了下DNS的格式&#xff0c;发现很多内容都是转载自同一个而且说的不是很清楚&#xff0c;特再整理下具体可以查看RFC1035 http://www.ietf.org/rfc/rfc1035.txt有详细的解释对于英语理解不是很好和懒得看这么长的可以看下本文首先是DNS数据帧的格式-------------------…

【Pix4d精品教程】Pix4d修编正射影像DOM的两种方法案例详解

《无人机航空摄影测量精品教程》合集目录(Pix4d、CC、EPS、PhotoScan、Inpho) DOM修编前: DOM修编后: 文章摘要: Pix4d内业数据处理通常会生成点云、DSM和DOM等产品,DSM经过精编可以生成精准的DEM,而DOM一般情况下,存在比如房屋边缘被拉花,或者存在噪点的情况

终于找到了,开源的Vue3+.NET6通用管理后台!

据说80%的.NET项目都是管理后台&#xff0c;然而能用上Vue3.NET6的管理后台并不多见。这里分享一套Vue3 Axios TS Vite ElementUI Plus .NET 6 WebAPI JWT SqlSugar的前后端分离架构的通用管理后台源码数据库脚本&#xff0c;还有与之配套录制的一组视频教程&#xff0c;全部打…

【Pix4d精品教程】Pix4d模型成果导出OSGB并加载OSGB到EPS进行三维测图完美案例教程

《无人机航空摄影测量精品教程》合集目录(Pix4d、CC、EPS、PhotoScan、Inpho) 在垂直摄影中,Pix4d也可以生成漂亮的三维模型,并导出为OSGB,加载到EPS进行三维测图。首先来看生成的三维格网纹理和EPS三维模型加载效果。 Pix4d生成的三维格网纹理: EPS加载OSGB模型效果: 文…

Android实现ListView(1)

昨天有个朋友问我Android ListView列表视图&#xff0c;遇到了点错误&#xff0c;今天我给大家演示&#xff0c;具体实现见图&#xff1a; 1&#xff1a;创建一个item布局layout/item.xml 2&#xff1a;创建一个ListViewActivity类&#xff0c;但是必须继承ListActivity&#x…

WolframAlpha 的使用

WolframAlpha 1. 求解复杂方程组 ab−4abc2ac1直接点开网站&#xff0c;在输入框中输入&#xff0c;ab-4;abc2;ac1;&#xff08;逗号分割开来&#xff09;&#xff0c; 转载于:https://www.cnblogs.com/mtcnn/p/9423087.html

聊聊 C# 中的 Composite 模式

‍写在前面 Composite组合模式属于设计模式中比较热门的一个&#xff0c;相信大家对它一定不像对访问者模式那么陌生&#xff0c;毕竟谁又没有遇到过树形结构呢。不过所谓温故而知新&#xff0c;我们还是从一个例子出发&#xff0c;起底一下这个模式吧。一个简单例子 设想我们…

140种Python标准库、第三方库和外部工具都有了

导读&#xff1a;Python数据工具箱涵盖从数据源到数据可视化的完整流程中涉及到的常用库、函数和外部工具。其中既有Python内置函数和标准库&#xff0c;又有第三方库和工具。 这些库可用于文件读写、网络抓取和解析、数据连接、数清洗转换、数据计算和统计分析、图像和视频处理…

开源项目【zheng】搭建流程

2019独角兽企业重金招聘Python工程师标准>>> 搭建过程 项目地址 https://gitee.com/shuzheng/zheng这两篇写的比较详细的搭建过程&#xff0c;结合一下就没什么问题了。 https://my.oschina.net/yzuzhang/blog/1538555http://www.jianshu.com/p/b2fb42e17b581.JDK 1…

简述HTML DOM及其节点分类

在JavaScript中&#xff0c;document这个对象大家一定很熟悉&#xff0c;哪怕是刚刚开始学习的新人&#xff0c;也会很快接触到这个对象。而document对象不仅仅是一个普通的JavaScript内置对象&#xff0c;它还是一个巨大API的核心对象&#xff0c;这个巨大的API就是DOM&#x…

【CC精品教程】任务二:导入像控点、差分POS,空三平差权重设置,提交自由空三

《无人机航空摄影测量精品教程》合集目录(Pix4d、CC、EPS、PhotoScan、Inpho) 【CC精品教程】任务一:CC新建工程、添加照片、相机参数设置、选择坐标系统 本任务接着上一个任务,继续完成CC项目作业,主要内容有:导入像控点、选择空间参考系统,导入差分POS,空三平差权重设…

WPF 基础控件之 TabControl样式

其他基础控件1.Window2.Button3.CheckBox4.ComboBox5.DataGrid 6.DatePicker7.Expander8.GroupBox9.ListBox10.ListView11.Menu12.PasswordBox13.TextBox14.RadioButton15.ToggleButton16.Slider 17.TreeView TabControl 实现下面的效果1&#xff09;TabControl来实现动画&…

两个数值交换位置

2019独角兽企业重金招聘Python工程师标准>>> 先说非计算机专业都能理解的。 int a 10; int b 20; 方法一&#xff1a; int c a; a b; b c; System.out.println("a"a",b"b); 方法二&#xff1a; a a b; b a - b; a a - b; System.out…

教你如何在Android 6.0上创建系统悬浮窗

郭霖大神的文章:http://mp.weixin.qq.com/s?__bizMzA5MzI3NjE2MA&mid2650235949&idx1&sn0f7eded67f834d38b02f8872768cb68a&scene0#wechat_redirect今天周二&#xff0c;又该跟大家分享由我执笔的文章了。从之前我写的deep links、通知栏微技巧这两篇文章中&a…

官宣.NET 7 预览版5

点击上方蓝字关注我们&#xff08;本文阅读时间&#xff1a;12分钟)今天我们发布了 .NET 7 预览版 5。.NET 7 的这个预览版包括对通用数学的改进&#xff0c;方便了 API 作者&#xff0c;使其更轻松&#xff0c;一个新的 ML.NET 文本分类 API&#xff0c;增加了最先进的深度学习…

[转]Android产品研发(十九)

转载请标明出处&#xff1a;一片枫叶的专栏 上一篇文章中我们讲解了webview中问题集锦&#xff0c;讲解了webview的性能优化、webview种入Cookie信息、activity退出的时候清除webview信息报错、如何通过java代码和js代码相互交互、webview如何下载文件以及腾讯的X5浏览服务等知…

【CC精品教程】ContextCapture 10.17安装教程(附CC10.17安装包下载)

《无人机航空摄影测量精品教程》合集目录(Pix4d、CC、EPS、PhotoScan、Inpho) CC10.17相比之前的版本有了好的新的功能和优点,在倾斜摄影测量中有了更多的优势,精度和运行速度有了很大的提升。本文讲解CC的安装,附CC10.17安装包下载,是您航测倾斜摄影测量的入门必备。 文…

mac SecureCRT设置

参考&#xff1a; http://www.2cto.com/os/201407/320292.html SecureCRT 设置 1&#xff09;每次登陆都要输入密码&#xff1a; Global Option -> General 取消&#xff1a;Use Keychain前面的勾 2&#xff09;Logon Actions Logon Actions很强大&#xff0c;和python里…

华为云GaussDB,11.11让企业无后顾之忧

每年11.11大促对于数据库而言都是一场生死考验&#xff0c;如何保障系统的稳定可靠&#xff0c;如何平稳度过业务流量洪峰期&#xff0c;如何高效扩容&#xff0c;成为每个参与活动客户的一大痛点。本文将通过5个常见的大促问题及分析&#xff0c;看看华为云GaussDB是如何解决这…

【CC精品教程】ContextCapture(CC)集群处理环境部署图文教程

《无人机航空摄影测量精品教程》合集目录(Pix4d、CC、EPS、PhotoScan、Inpho) 鉴于CC其三维构建运算的本质,海量数据的解析运算会使用大量的计算机资源,而再好的单台计算机也无法胜过多台计算机的并行运算能力,故而借助局域网内多台计算机设备进行三维构建运算,可以节省大…