在Blazor使用Fluent UI元件 - 1
Fluent UI Blazor 是一個由微軟開發的開源元件庫,可以讓程式開發人員在 Blazor 應用程式中使用 Fluent UI 來設計系統。Fluent UI 是一種設計套件,可幫助開發人員建立美觀、一致且易於使用的使用者介面。
Fluent UI Blazor 元件庫目前包含了超過 40 幾個元件,涵蓋了應用程式或網站中常見的使用者介面元素,例如按鈕、文字方塊、下拉式選單、表格、圖表等等。這些元件經過精心設計,可與 Fluent UI 設計系統的其餘部分無縫整合。
Fluent UI Blazor 元件庫的主要功能包括:
• 豐富的元件庫:包含超過 40 幾個常用元件,可滿足各種使用者介面需求。
• 易於使用:元件採用簡單易懂的 API,可快速上手,學習曲線短。
• 允許客製化:元件可根據需要進行客製化,以符合特定的設計的要求。
• 無障礙性:元件遵循無障礙性最佳做法,可供所有人使用。
Fluent UI Blazor 元件庫適用於以下場景:
• 建立新的 Blazor 應用程式。
• 將 Fluent UI 設計系統到用到現有的 Blazor 應用程式之中。
• 加速 Blazor 應用程式的使用者介面設計動作。
使用 Fluent UI Blazor 元件庫的優點包括:
• 可提高開發效率:使用現成的元件可節省開發時間和精力。
• 提升使用者體驗:Fluent UI 設計系統可幫助建立美觀、一致且易於使用的使用者介面。
• 降低維護成本:元件經過良好測試和維護,可降低應用程式的維護成本。
在這一篇文章中,我們將介紹一些適用於.NET 8,可在Blazor應用程式使用的Fluent UI元件基本功能。
安裝 Microsoft.FluentUI.AspNetCore.Templates套件
想要在Blazor應用程式之中開始使用 Fluent UI Blazor 元件進行設計的最簡單方法,就是利用官方提供的專案範本。專案範本可從以下網址下載:
https://www.nuget.org/packages/Microsoft.FluentUI.AspNetCore.Templates
請參考下圖所示:
圖 1:專案範本。
在作業系統命令提示字元執行下列命令來安裝套件範本:
dotnet new install Microsoft.FluentUI.AspNetCore.Templates::4.6.0
執行結果請參考下圖所示:
圖 2:安裝套件範本。
範本安裝完成之後,就可以透過Visual Studio 2022來建立專案。
建立Blazor專案
首先使用Visual Studio 2022開發工具建立一個Blazor專案,建立步驟如下:啟動Visual Studio 2022開發環境,從「開始」視窗選取「Create a new project」選項。從Visual Studio 2022開發工具的「Create a new project」對話盒中,你可以看到許多「Fluent Blazor」字串開頭的範本,請參考下圖所示:
圖 3:「Blazor Web App 」項目。
選取「Create a new project」對話盒中的「Fluent Blazor Web App 」項目,然後按一下「Next」按鈕,下一步,在「Configure your new project」視窗中,設定Blazor專案名稱與專案存放路徑,然後按下「Next」按鈕,請參考下圖所示:
圖 4:設定Blazor專案名稱與專案存放路徑。
下一步,在「Additional information」視窗中,設定「Target Framework」為「NET 8.0 (Long Term Support)」;將「Authentication Type」設為「None」;「Interactive render mode」選擇「Auto(Server and WebAssembly)」;「Interactivity location」設定為「Per page/component」,然後勾選「Include sample pages」,然後按下「Create」按鈕,請參考下圖所示:
圖 5:設定「Target Framework」為「NET 8.0 (Long Term Support)」。
專案建立完成之後,從「Solution Explorer」視窗中可以看到目前包含兩個專案:其中「BlazorFluentUI」是伺服端專案,專案中包含的是Blazor Server元件;「BlazorFluentUI.Client」是用戶端專案,這專案將會以WebAssmbly的方式執行在用戶端瀏覽器,請參考下圖所示:
圖 6:專案結構。
從伺服端專案的「Packages」項目中,可以看到其中包含FluentUI相依套件,請參考下圖所示:
圖 7:伺服端專案FluentUI相依套件。
同樣在用戶端專案中,也可以看到其中包含FluentUI相依套件,請參考下圖所示:
圖 8:用戶端專案FluentUI相依套件。
在Visual Studio 2022開發工具,按CTRL+F5執行網站,目前網站首頁的執行結果參考如下圖所示,
圖 9:範本網站執行結果。
讓我們探討一下專案範本的基本設定,在「Program.cs」檔案中可以看到這行程式碼「builder.Services.AddFluentUIComponents();」設定 Dependency Injection (DI) 容器,將 Fluent UI 的組件註冊到 DI 容器中。這樣在其他地方需要使用這些組件時,就可以透過 DI 容器來取得,而不需要手動創建實例。這種方式可以提高程式的模組化和可測試性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | using BlazorFluentUI.Client.Pages;using BlazorFluentUI.Components;using Microsoft.FluentUI.AspNetCore.Components;var builder = WebApplication.CreateBuilder( args );// Add services to the container.builder.Services.AddRazorComponents( ) .AddInteractiveServerComponents( ) .AddInteractiveWebAssemblyComponents( );builder.Services.AddFluentUIComponents( );var app = builder.Build( );// Configure the HTTP request pipeline.if ( app.Environment.IsDevelopment( ) ) { app.UseWebAssemblyDebugging( );}else { app.UseExceptionHandler( "/Error", createScopeForErrors: true ); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts( );}app.UseHttpsRedirection( );app.UseStaticFiles( );app.UseAntiforgery( );app.MapRazorComponents<App>( ) .AddInteractiveServerRenderMode( ) .AddInteractiveWebAssemblyRenderMode( ) .AddAdditionalAssemblies( typeof( BlazorFluentUI.Client._Imports ).Assembly );app.Run( ); |
在「MainLayout.razor」檔案可看到預設使用 Fluent UI 的組件來定義一個網頁的基本版面配置,以確保所有網頁的外觀和風格一致,參考以下範例程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | @inherits LayoutComponentBase<FluentLayout> <FluentHeader> BlazorFluentUI </FluentHeader> <FluentStack Class = "main" Orientation = "Orientation.Horizontal" Width = "100%"> <NavMenu /> <FluentBodyContent Class = "body-content"> <div class = "content"> @Body </div> </FluentBodyContent> </FluentStack> <FluentFooter> <div class = "link1"> </div> <div class = "link2"> <a href = "https://learn.microsoft.com/en-us/aspnet/core/blazor" target = "_blank"> About Blazor </a> </div> </FluentFooter></FluentLayout><div id = "blazor-error-ui"> An unhandled error has occurred. <a href = "" class = "reload"> Reload </a> <a class = "dismiss"> x </a></div> |
使用了 Razor 語法定義 Blazor 組件的版面。它使用了 Fluent UI 的組件來建立一個具有表頭、主體和表尾的網頁版面。其中的組件說明如下:
FluentLayout: 這是一個容器組件,用於包含整個頁面的版面。
FluentHeader: 這是表頭組件,顯示網站的名稱為「BlazorFluentUI」。
FluentStack: 這是一個堆疊組件,用於將子組件以堆疊的方式排列。在這裡,它包含了一個導覽選單 () 和主體內容 ()。
FluentBodyContent : 這是主體內容組件,裡面的 @Body 是一個 Razor定位點,用於插入其他 Razor 組件或 HTML 內容。
FluentFooter : 這是表尾組件,裡面包含了兩個連結,分別指向 Fluent UI 的文檔和關於 Blazor 的資訊。
用戶端有一個「Counter.razor」組件,參考以下程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | @page "/counter"@rendermode InteractiveAuto<PageTitle> Counter </PageTitle><h1> Counter </h1><div role = "status" style = "padding-bottom: 1em;"> Current count: <FluentBadge Appearance = "Appearance.Neutral"> @currentCount </FluentBadge></div><FluentButton Appearance = "Appearance.Accent" @onclick = "IncrementCount"> Click me </FluentButton>@code { private int currentCount = 0; private void IncrementCount() { currentCount++; }} |
「Counter.razor」組件使用了 Fluent UI 的「FluentBadge」組件來顯示當前的計數值,以及Fluent UI 的 FluentButton 組件做為一個可以點擊來增加計數值的按鈕,「Appearance = "Appearance.Accent」 是用來設定這個按鈕的外觀風格。「Counter.razor」組件執行的結果,請參考下圖所示:
圖 10:使用Fluent UI組件設計組件畫面。
再來看看伺服端專案的「Weather.razor」組件程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | @page "/weather"@attribute [StreamRendering]<PageTitle> Weather </PageTitle><h1> Weather </h1><p> This component demonstrates showing data. </p>@if ( forecasts == null ){ <p><em> Loading... </em></p>}else{ <!-- This page is rendered in SSR mode, so the FluentDataGrid component does not offer any interactivity (like sorting). --> <FluentDataGrid Id = "weathergrid" Items = "@forecasts" GridTemplateColumns = "1fr 1fr 1fr 2fr" TGridItem = "WeatherForecast"> <PropertyColumn Title = "Date" Property = "@(c => c!.Date)" Align = "Align.Start"/> <PropertyColumn Title = "Temp. (C)" Property = "@(c => c!.TemperatureC)" Align = "Align.Center"/> <PropertyColumn Title = "Temp. (F)" Property = "@(c => c!.TemperatureF)" Align = "Align.Center"/> <PropertyColumn Title = "Summary" Property = "@(c => c!.Summary)" Align = "Align.End"/> </FluentDataGrid>}@code { private IQueryable<WeatherForecast>? forecasts; protected override async Task OnInitializedAsync() { // Simulate asynchronous loading to demonstrate streaming rendering await Task.Delay(500); var startDate = DateOnly.FromDateTime( DateTime.Now ); var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; forecasts = Enumerable.Range(1, 5).Select( index => new WeatherForecast { Date = startDate.AddDays( index ), TemperatureC = Random.Shared.Next( -20, 55 ), Summary = summaries[ Random.Shared.Next(summaries.Length) ] }).AsQueryable(); } private class WeatherForecast { public DateOnly Date { get; set; } public int TemperatureC { get; set; } public string? Summary { get; set; } public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); }} |
「Weather.razor」組件程式使用了 Fluent UI 的「FluentDataGrid」組件來顯示一個天氣預報的表格資料。「FluentDataGrid」組件的屬性設定如下:
「Virtualize = "true"」: 啟用虛擬化,這可以提高大量數料集的渲染效能。
「Items = "@forecasts":」:設定資料來源為「forecasts」。
「GridTemplateColumns = "1fr 1fr 1fr 2fr"」: 設定表格的欄寬,這裡定義了四個直欄,每個直欄的寬度分別為 1fr、1fr、1fr 和 2fr。
「TGridItem = "WeatherForecast」: 設定表格的資料類型為「WeatherForecast」。
「PropertyColumn」組件用於定義表格的直欄。每個 PropertyColumn 組件透過資料繫結關聯到「WeatherForecast」型別的一個屬性,並設定了直欄的標題 (Title)和對齊方式 (Align)。
「Weather.razor」組件執行的結果,請參考下圖所示,可以看到畫面中的表格,顯示天氣預報的資訊,包括日期、攝氏溫度、華氏溫度和天氣總結。並且,每格直欄都可以進行排序,用戶可以點擊直欄的標題來變更資料的排序方式。
圖 11:「FluentDataGrid」組件。
使用Sortable設定排序
Blazor 提供了三種渲染模式:Server、WebAssembly 和 ServerPrerendered。「InteractiveServer」模式是Server渲染的一種模式,在「InteractiveServer」模式下,組件的執行和狀態管理都在伺服器端進行,並通過 SignalR 連線與客戶端進行即時的通訊。當用戶與組件互動(如點擊按鈕),事件會被發送到伺服器端進行處理,然後伺服器端將更新的 UI 差異發送回客戶端進行渲染。
Fluent UI提供的組件有些只能夠在伺服端專案渲染,不能在用戶端渲染,例如的排序功能就必需設定成伺服端渲染,要設定 Blazor 組件的渲染模式,可以使用「@rendermode」,修改程式如下,將「@rendermode」設為「InteractiveServer」;然後將「PropertyColumn」的「Sortable」設定為「true」:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | @page "/weather"@attribute [StreamRendering]<PageTitle> Weather </PageTitle><h1> Weather </h1><p> This component demonstrates showing data. </p>@if ( forecasts == null ){ <p><em> Loading... </em></p>}else{ <!-- This page is rendered in SSR mode, so the FluentDataGrid component does not offer any interactivity (like sorting). --> <FluentDataGrid Id = "weathergrid" Items = "@forecasts" GridTemplateColumns = "1fr 1fr 1fr 2fr" TGridItem = "WeatherForecast"> <PropertyColumn Title = "Date" Property = "@(c => c!.Date)" Align = "Align.Start"/> <PropertyColumn Title = "Temp. (C)" Property = "@(c => c!.TemperatureC)" Align = "Align.Center"/> <PropertyColumn Title = "Temp. (F)" Property = "@(c => c!.TemperatureF)" Align = "Align.Center"/> <PropertyColumn Title = "Summary" Property = "@(c => c!.Summary)" Align = "Align.End"/> </FluentDataGrid>}@code { private IQueryable<WeatherForecast>? forecasts; protected override async Task OnInitializedAsync() { // Simulate asynchronous loading to demonstrate streaming rendering await Task.Delay(500); var startDate = DateOnly.FromDateTime( DateTime.Now ); var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; forecasts = Enumerable.Range(1, 5).Select( index => new WeatherForecast { Date = startDate.AddDays( index ), TemperatureC = Random.Shared.Next( -20, 55 ), Summary = summaries[ Random.Shared.Next(summaries.Length) ] }).AsQueryable(); } private class WeatherForecast { public DateOnly Date { get; set; } public int TemperatureC { get; set; } public string? Summary { get; set; } public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); }} |
「Weather.razor」組件執行的結果,請參考下圖所示,點選欄位表頭就可以進行排序:
圖 12:使用Sortable設定排序。
另一種設定「@rendermode」的方式是改用路由,如此個別元件就不需要進行設定,在「App.razor」加入以下程式碼:
App.razor
虛擬化(Virtualize)
FluentDataGrid 有一個「Virtualize」選項,用於啟用組件的虛擬化功能。虛擬化是一種效能優化的技術,用於處理大量的資料。當啟用虛擬化時,Blazor 只會渲染當前在視窗中可見的部分資料,而不是渲染整個資料集。當用戶捲動視窗時,Blazor 會自動地新增和移除元素,以確保只有可見的部分被渲染。這種方式可以大大提高渲染大型資料集的效能,因為它避免了不必要的渲染工作。這對於那些需要顯示大量資料的應用來說,是非常有用的。
我們先試試沒有啟用虛擬化時,程式運作的情況,首先修改Weather.razor程式碼,將Enumerable.Range方法第二個參數設定為「2000」模擬大量天氣資料,參考以下程式碼:
1 2 3 4 5 6 | forecasts = Enumerable.Range( 1, 2000 ).Select( index => new WeatherForecast{ Date = startDate.AddDays( index) , TemperatureC = Random.Shared.Next( -20, 55 ), Summary = summaries[ Random.Shared.Next(summaries.Length) ]}).AsQueryable(); |
「Weather.razor」組件執行的結果,請參考下圖所示,所有資料一次呈現在網頁上:
圖 13:未啟用虛擬化。
修改「FluentDataGrid」組件程式碼,設定「Virtualize = "true"」,參考以下程式碼:
1 2 3 4 5 6 | <FluentDataGrid Virtualize = "true" Id = "weathergrid" Items = "@forecasts" GridTemplateColumns = "1fr 1fr 1fr 2fr" TGridItem = "WeatherForecast"> <PropertyColumn Title = "Date" Sortable = "true" Property = "@(c => c!.Date)" Align = "Align.Start"/> <PropertyColumn Title = "Temp. (C)" Sortable = "true" Property = "@(c => c!.TemperatureC)" Align = "Align.Center" /> <PropertyColumn Title = "Temp. (F)" Sortable = "true" Property = "@(c => c!.TemperatureF)" Align = "Align.Center" /> <PropertyColumn Title = "Summary" Sortable = "true" Property = "@(c => c!.Summary)" Align = "Align.End" /> </FluentDataGrid> |
這次「Weather.razor」組件執行的結果,請參考下圖所示,第一次只載入部份資料,當捲動畫面到下方時,才動態呈現其它資料:
圖 14:啟用虛擬化。
總結
微軟的 Fluent UI Blazor 元件庫雖然是開源項目,但它並不是 ASP.NET Core 的正式組成部分,因此沒有官方支援,也不保證會與任何 .NET 更新一起發佈。儘管如此,它仍然由微軟員工 (和其他貢獻者) 建置和維護,並提供與大多數其他開源項目類似的支援,利用 GitHub 倉庫盡力協助使用者。
Fluent UI Blazor 元件庫是一個功能強大且易於使用的工具,可幫助開發人員在 Blazor 應用程式中使用 Fluent UI 設計系統。如果您正在尋找一種方法來提升 Blazor 應用程式的使用者介面設計,那麼 Fluent UI Blazor 元件庫是一個不錯的選擇。
.png)
.png)
.png)
.png)
.png)
.png)
.png)
.png)
.png)
.png)
.png)
.png)
.png)
.png)
0 意見:
張貼留言