1. 前言
距离上次发《MAUI 初体验:爽》一文已经过去 2 个月了,本计划是下半年或者明年再研究 MAUI 的,现在计划提前啦,因为我觉得 MAUI Blazor 挺有意思的:在 Android、iOS、macOS、Windows 之间共享 UI,一处 UI 增加或者修改,就能得到一致的 UI 体验。
看看这篇文章《Blazor Hybrid/MAUI 简介和实战》对 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:https://server.dotnet9.com/
- Blazor Wasm:https://wasm.dotnet9.com/
- maui(android\windows\macos):https://github.com/dotnet9/dotnet9/tree/develop/src/dotnet9.maui(源碼自行編譯)
windows 桌面、blazor server(在線)、blazor wasm(在線)、android 效果

ipad air、ios、macos 桌面效果

maui 各端未做發布文件體驗(需要做相應平台的發布簽名等操作),大家可以按下面居間的方法創建項目編譯體驗一下。
iOS 和 macOS 效果感谢青城同学提供的图片素材,站长 mbp 安装了最新的 macOS,xCode 也是最新的,可能因为预览版 macOS 原因,xCode 无法打开,间接影响了 maui 编译?
macos 版本和 xcode 版本

xcode 為不可用狀態

vs 編譯出錯,後面再解決

用 mbp 的同學建議不要安裝預覽版作業系統,不要當勇士....
3. 新建項目
关于 MAUI 的环境搭建可参考这篇文章《在 MAUI 中使用 Masa Blazor》,本文不再介绍环境搭建,直接使用 VS 2022 最新预览版项目模板创建项目。
3.1創建 blazor server 項目:dotnet9.server

3.2創建 blazor webassembly 項目:dotnet9.wasm

3.3創建 maui blazor 項目:dotnet9.maui

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

仔細查看三個模板項目文件結構,我們找出共同的文件查看:
文件夹 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

下面開始 ui 的提取

如上图,将Dotnet9.MAUI项目的Data、Pages、Shared三个目录外加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 項目
- 添加
Dotnet9.WebApp项目引用 Program.cs中using Dotnet9.MAUI.Data;改为using Dotnet9.WebApp.Data- 删除
Data、Pages、Shared三个目录外加Main.razor文件,上一步是剪切的话这步省略 - 修改
_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
MauiProgram.cs修改引用的命名空间:using Dotnet9.MAUI.Data;=>using Dotnet9.WebApp.Data;- 打开
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 項目
- 添加
Dotnet9.WebApp项目引用 Program.cs中using Dotnet9.Server.Data;改为using Dotnet9.WebApp.Data;- 删除
Data目录 - 删除
Pages目录中的Counter.razor、FetchData.razor、Index.razor三个文件(包括同名的.cs、.css文件) - 删除
Shared目录 - 修改
_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
- 删除
App.razor文件,打开./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 項目
- 添加
Dotnet9.WebApp项目引用 - 删除
Pages、Shared目录外加App.razor文件 Program.cs中using Dotnet9.Wasm;改为using Dotnet9.WebApp;,同时修改代码
修改前
builder.RootComponents.Add<App>("#app");
修改後
builder.RootComponents.Add<Main>("#app");
- 修改
_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项目,至此三种项目模板已经修改完成,最终解决方案如下图:

6 總結
總結就是下圖:

- dotnet9.webapp:blazor 組件相關的代碼、路由組件等放在這個工程,供其他項目引用
- dotnet9.server:blazor server 模板項目
- dotnet9.wasm:blazor webassembly 項目
- dotnet9.maui:maui blazor 項目
一句话:将 UI 封装到 Razor 类库Dotnet9.WebApp,其他终端工程(Dotnet9.Server、Dotnet9.MAUI、Dotnet9.Wasm)引用此工程即可实现 UI 共享。
- 本文代码地址:https://github.com/dotnet9/Dotnet9
- 原文:https://dotnet9.com/2022/06/Share-razor-library-between-maui-and-blazor-server-or-client
參考