在Blazor使用Fluent UI元件-5
作 者:恆逸資深講師 許薰尹
在本站《在Blazor使用Fluent UI元件 - 4》一文介紹如何在現有的Blazor專案中,手動加入Fluent UI元件 ,並使用「FluentDialog」元件設計確認刪除的對話盒。在這一篇文章中,我們將介紹延續這系列文章的情境,介紹該如何自訂對話盒,以便讓其它元件能夠重複使用這個對話盒。
設計MyDialog
首先讓我們使用元件來自訂對話盒,元件的程式碼可放在專案根目錄下的「Shared」資料夾。從「Solution Explorer」視窗 - 專案名稱上方按滑鼠右鍵,從快捷選單選擇「Add」- 「New Folder」選項,將新建立的資料夾命名為「Shared」。
在「Shared」資料夾中加入Razor元件,從「Solution Explorer」視窗 -「Shared」資料夾上方,按滑鼠右鍵,從快捷選單選擇「Add」- 「Razro Component」項目,將元件名稱命為「MyDialog.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 | @ using Microsoft.FluentUI.AspNetCore.Components @implements IDialogContentComponent<FluentUIDataGrid.Models.Customer> @* Header *@ <FluentDialogHeader ShowDismiss = "true" > <FluentStack VerticalAlignment = "VerticalAlignment.Center" > <FluentIcon Value = "@(new Icons.Regular.Size24.WindowApps())" /> <FluentLabel Typo = "Typography.PaneHeader" > @Dialog.Instance.Parameters.Title </FluentLabel> </FluentStack> </FluentDialogHeader> @* Footer *@ <FluentDialogFooter> <FluentButton Appearance = "Appearance.Accent" OnClick = "@DeleteAsync" > Delete </FluentButton> <FluentButton Appearance = "Appearance.Neutral" OnClick = "@CancelAsync" > Cancel </FluentButton> </FluentDialogFooter> @* Body *@ <FluentDialogBody> <FluentTextField @bind-Value = "@Content.CustomerId" > CustomerId: </FluentTextField> <FluentTextField @bind-Value = "@Content.CompanyName" > CompanyName: </FluentTextField> <FluentTextField @bind-Value = "@Content.ContactName" > ContactName: </FluentTextField> </FluentDialogBody> @code { [Parameter] public FluentUIDataGrid.Models.Customer Content { get ; set ; } = default !; [CascadingParameter] public FluentDialog Dialog { get ; set ; } = default !; private async Task DeleteAsync() { await Dialog.CloseAsync( Content ); } private async Task CancelAsync() { await Dialog.CancelAsync( ); } } |
分別說明如下,以下這兩行程式碼是在引入了必要的命名空間,並且實作了「IDialogContentComponent」介面,該介面的泛型參數是「FluentUIDataGrid.Models.Customer」:
1 2 | @ using Microsoft.FluentUI.AspNetCore.Components @implements IDialogContentComponent<FluentUIDataGrid.Models.Customer> |
以下程式碼建立了自訂對話盒的標題部分。「FluentDialogHeader」是對話盒的標題,「ShowDismiss」屬性設為「true」表示可以關閉對話盒。「FluentStack」是一個容器類型的元件,裡面包含了一個圖示(FluentIcon)和一個標籤(FluentLabel),這個標籤顯示的是對話盒的標題:
1 2 3 4 5 6 7 8 9 | @* Header *@ <FluentDialogHeader ShowDismiss = "true" > <FluentStack VerticalAlignment = "VerticalAlignment.Center" > <FluentIcon Value = "@(new Icons.Regular.Size24.WindowApps())" /> <FluentLabel Typo = "Typography.PaneHeader" > @Dialog.Instance.Parameters.Title </FluentLabel> </FluentStack> </FluentDialogHeader> |
以下程式碼建立對話盒的尾部部分。「FluentDialogFooter」是對話盒的底部,裡面包含了兩個按鈕,一個是刪除按鈕,點擊後會執行「DeleteAsync」方法,另一個是取消按鈕,點擊後會執行「CancelAsync」方法。
1 2 3 4 5 | @* Footer *@ <FluentDialogFooter> <FluentButton Appearance = "Appearance.Accent" OnClick = "@DeleteAsync" > Delete </FluentButton> <FluentButton Appearance = "Appearance.Neutral" OnClick = "@CancelAsync" > Cancel </FluentButton> </FluentDialogFooter> |
以下程式碼建立對話盒的主體部分。「FluentDialogBody」是對話盒的主體,裡面包含了三個文字欄位,分別繫結到「Content」物件的「CustomerId」、「CompanyName」和「ContactName」屬性。
1 2 3 4 5 6 | @* Body *@ <FluentDialogBody> <FluentTextField @bind-Value = "@Content.CustomerId" > Id: </FluentTextField> <FluentTextField @bind-Value = "@Content.CompanyName" > CompanyName: </FluentTextField> <FluentTextField @bind-Value = "@Content.ContactName" > ContactName: </FluentTextField> </FluentDialogBody> |
以下程式碼定義一些屬性和方法。「Content」屬性是一個參數,它的類型是「FluentUIDataGrid.Models.Customer」。「Dialog」性是一個「CascadingParameter」參數,它的類型是「FluentDialog」。「DeleteAsync」方法是在刪除按鈕被按下時執行,它會關閉對話盒並傳遞「Content」物件。「CancelAsync」方法是在取消按鈕被按下時執行,它會取消對話盒。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @code { [Parameter] public FluentUIDataGrid.Models.Customer Content { get ; set ; } = default !; [CascadingParameter] public FluentDialog Dialog { get ; set ; } = default !; private async Task DeleteAsync() { await Dialog.CloseAsync( Content ); } private async Task CancelAsync() { await Dialog.CancelAsync( ); } } |
下一步在「MyDataGridComponent.razor」元件中使用「MyDialog」對話盒。參考以下程式碼,當按下「FluentDataGrid 」任一筆資料右方的刪除按鈕時,便叫用「DialogService.ShowDialogAsync()」方法顯示自訂對話盒:
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 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | @ using FluentUIDataGrid.Models @ using Microsoft.EntityFrameworkCore @inject NorthwindContext DbContext @inject IDialogService DialogService <h3>MyDataGridComponent</h3> <FluentDataGrid TGridItem = "Customer" Items = "Customers" GridTemplateColumns = "1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr" > <PropertyColumn Property = "@(c => c.CustomerId)" Sortable = "true" /> <PropertyColumn Property = "@(c => c.CompanyName)" Sortable = "true" /> <PropertyColumn Property = "@(c => c.ContactName)" Sortable = "true" /> <PropertyColumn Property = "@(c => c.ContactTitle)" Sortable = "true" /> <PropertyColumn Property = "@(c => c.Address)" Sortable = "true" /> <PropertyColumn Property = "@(c => c.City)" Sortable = "true" /> <PropertyColumn Property = "@(c => c.Country)" Sortable = "true" /> <TemplateColumn Title = "Actions" > <FluentButton IconStart = "@(new Icons.Regular.Size20.Delete())" OnClick = "@( () => DeleteClicked(context) )" > Delete </FluentButton> </TemplateColumn> </FluentDataGrid> @code { public async Task DeleteClicked( Customer customer ) { var dialog = await DialogService.ShowDialogAsync<FluentUIDataGrid.Shared.MyDialog>( customer, new DialogParameters { Height = "240px" , Title = $ "Delete Customer : { customer.CustomerId }" , PreventDismissOnOverlayClick = true , PreventScroll = true } ); var result = await dialog.Result; if ( !result.Cancelled && result.Data != null ) { var c = await DbContext.Customers.FirstOrDefaultAsync( c => c.CustomerId == customer.CustomerId ); DbContext.Customers.Remove( c ); if ( c is not null ) { await DbContext.SaveChangesAsync( ); } } } public IQueryable<Customer> Customers { get ; set ; } = null !; protected override async Task OnInitializedAsync() { await Task.Run( () => { Customers = DbContext.Customers.AsQueryable( ); } ); } } <style> .dialog-box { background-color: #f2f2f2; border: 1px solid #ccc; border-radius: 4px; padding: 10px; margin-bottom: 10px; } .dialog-title { font-size: 18px; font-weight: bold; margin-bottom: 10px; } .dialog-buttons { margin-top: 10px; } .dialog-buttons button { margin-right: 10px; } </style> |
分別說明如下,以下這段程式碼,叫用「DialogService.ShowDialogAsync()」方法顯示對話盒,傳入了一個「customer」物件和一個「DialogParameters」物件來設定對話盒的參數,「Height」設定高度、「Title」設定標題、「PreventDismissOnOverlayClick」是否防止點選背景來關閉對話盒,「PreventDismissOnOverlayClick」設定為「true」時不可以點選背景來關閉對話盒;「PreventDismissOnOverlayClick」設為「false」則可以點選背景來關閉對話盒、「PreventScroll」用來設定是否防止滾動。
1 2 3 4 5 6 7 | var dialog = await DialogService.ShowDialogAsync<FluentUIDataGrid.Shared.MyDialog>( customer, new DialogParameters { Height = "240px" , Title = $ "Delete Customer : { customer.CustomerId }" , PreventDismissOnOverlayClick = true , PreventScroll = true } ); |
以下這行程式碼是在等待對話盒關閉並獲取結果,如果對話盒沒有被取消且返回的資料不為空,則進行以下操作:首先,從資料庫中找尋與當前「customer」的「CustomerId」相符的「Customer」物件。然後,從「DbContext.Customers」移除該筆資料。最後,如果「CustomerId」相符的資料存在於資料庫,則刪除資料庫的資料:
1 2 3 4 5 6 7 8 | var result = await dialog.Result; if ( !result.Cancelled && result.Data != null ) { var c = await DbContext.Customers.FirstOrDefaultAsync( c => c.CustomerId == customer.CustomerId ); DbContext.Customers.Remove( c ); if ( c is not null ) { await DbContext.SaveChangesAsync( ); } } |
這個範例的執行結果請參考下圖所示:
圖 1:自訂對話盒。
0 意見:
張貼留言