距離上次發《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修改)。
Windows桌面、Blazor Server(線上)、Blazor Wasm(線上)、Android效果
iPad Air、iOS、macOS桌面效果
MAUI各端未做釋出檔案體驗(需要做相應平臺的釋出簽名等操作),大家可以按下面介紹的方法建立專案編譯體驗一下。
iOS和macOS效果感謝青城同學提供的圖片素材,站長mbp安裝了最新的macOS,xCode也是最新的,可能因為預覽版macOS原因,xCode無法開啟,間接影響了maui編譯?
macOS版本和xCode版本
xCode為不可用狀態
VS編譯出錯,後面再解決
用mbp的同學建議不要安裝預覽版作業系統,不要當勇士....
關於MAUI的環境搭建可參考這篇文章《在MAUI中使用Masa Blazor》,本文不再介紹環境搭建,直接使用VS 2022最新預覽版專案模板建立專案。
在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{}
中的),那把這部分檔案直接提取到類庫中就可以了,那就做吧。
建立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
專案,檢查是否正確編譯。
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
專案。
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
./Pages/_Host.cshtml
檔案,新增名稱空間參照@using Dotnet9.WebApp
,修改程式碼如下:修改前:
<component type="typeof(App)" render-mode="ServerPrerendered" />
修改後:
<component type="typeof(Main)" render-mode="ServerPrerendered" />
修改完畢,編譯執行Dotnet9.Server
專案吧,接下來修改Dotnet9.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
專案,至此三種專案模板已經修改完成,最終解決方案如下圖:
總結就是下圖:
一句話:將UI封裝到Razor類庫Dotnet9.WebApp
,其他終端工程(Dotnet9.Server
、Dotnet9.MAUI
、Dotnet9.Wasm
)參照此工程即可實現UI共用。
參考