2018年12月6日 星期四

Blazor 4 Bootstrap 對話窗顯示與關閉練習

Blazor 4 Bootstrap 對話窗顯示與關閉練習

更多關於 Blazor 教學影片,可以參考 Blazor 教學影片播放清單 或者 Blazor 快速體驗教學影片撥放清單。也歡迎訂閱本 .NET / Blazor / Xamarin.Forms 影片頻道 。

通常在進行開發一個類似 CRUD 的應用程式,使用者可能會點選某一筆紀錄,接著進行修該該紀錄的內容,接著就會點選 儲存 按鈕,此時大多會在網頁上顯示一個對話窗,詢問使用者是否要儲存該筆紀錄,不會使用者點選了 確定 或者 放棄 按鈕,該對話窗將會從螢幕上再度隱藏並且消失了。在這篇文章中,將會說明如何使用 Blazor 開發出這樣的應用,當然,還是秉持著完全都使用 .NET C# 的方式,而沒有使用到 JavaScript 來進行開發的精神;在這裡使用了 Bootstrap Modal 功能,來模擬使用者要刪除一筆員工紀錄的時候,會顯示一個對話窗詢問使用者,真的要刪除這筆紀錄嗎?該對話窗內會有該員工紀錄的詳細資料,並且還有兩個按鈕,分別是 是 與 否,而不論使用者點選了哪個按鈕,在這個元件上都會有一個 .NET C# 的按鈕事件綁定在一起。本篇文章的範例原始碼,可以從 BlazorModal 取得。

建立測試專案

現在可以開始建立第一個 Blazor 開發專案。
  • 啟動 Visual Studio 2017
  • 點選功能表的 [檔案] > [新增] > [專案] 功能表選項
  • 在 [新增專案] 對話窗中左邊區域,選擇 [已安裝] > [Visual C#] > [Web] > [ASP.NET Core Web 應用程式]
  • 在對話窗的下方的 [名稱] 欄位中,輸入這個練習專案的名稱 BlazorModal
  • 在對話窗的下方的 [位置] 欄位中,選擇這個專案要儲存的檔案路徑
  • 最後點選對話窗的右下方 [確定] 按鈕
  • 在 [新增 ASP.NET Core Web 應用程式] 對話窗左上方區域,在第一個下拉選單,選擇 [.NET Core] 在第二個下拉選單,請選擇最新的 ASP.NET Core 版本,在現在這個時間點,可以選擇 [ASP.NET Core 2.1]
  • 在對話窗中間區域,請點選 [Blazor] 這個項目
  • 最後點選對話窗的右下方 [確定] 按鈕

修正 Counter 元件,發佈特定事件通知

為了要做到上面提到的效果,在這裡進行修正了 Counter 元件的原始碼,當使用者按下 Click me 按鈕,且 currentCount 變數值為偶數,則將會顯示出來這個對話窗。
該對話窗已經宣告在這個元件上,不過,預設因為變數 ShowDialog 為 false,所以,該對話窗的內容不會顯示在網頁上,因此,當 currentCount 變數值為偶數的時候,將會把 ShowDialog 變數值為 true,也因此<div class="modal " tabindex="-1" style="display:block" role="dialog">...</div> 這些 HTML 標記就會顯示在網頁上,也就是該對話窗內容。
在該對話窗上的兩個回應按鈕,也透過了 Blazor 的按鈕事件綁定方式,綁定到該元件內的特定方法,例如,對於 是 這個按鈕,將會使用 <button class="btn btn-danger" onclick="@CloseModalYes">是</button> 這樣的標籤來宣告,當按下了這個按鈕之後,將會執行該元件內的 CloseModalYes 委派事件方法,此時,該變數 DeleteResult 將會設定為 是的,刪除這筆員工資料 這個文字字串,而該變數也綁定在網頁之上,因此,在網頁上也會看到這個文字;而對於 否 按鈕,將會使用 <button class="btn btn-warning" onclick="@CloseModalNo">否</button> 這個 HTML 標籤來宣告,當 CloseModalNo 方法被觸發之後,因為變數 DeleteResult 將會設定為 不,放棄刪除這筆員工資料 這個文字字串,而該變數也綁定在網頁之上,因此,在網頁上也會看到這個文字。
現在,請依照底下說明來修正專案程式碼
  • 請打開 [Pages] 資料夾內的 [Counter.cshtml] 檔案
  • 使用底下程式碼替換掉 [Counter.cshtml] 檔案內容
 Pages > Counter.cshtml
@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" onclick="@IncrementCount">Click me</button>

<p>刪除選擇:@DeleteResult</p>

<div class="modal" role="dialog">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                <h4 class="modal-title">Modal title</h4>
            </div>
            <div class="modal-body">
                <p>Contents go here...</p>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-primary" data-dismiss="modal">Close</button>
            </div>
        </div>
    </div>
</div>
@if (ShowDialog)
{
    <div class="modal " tabindex="-1" style="display:block" role="dialog">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <h3 class="modal-title">刪除員工資料</h3>
                </div>
                <div class="modal-body">
                    <h4>你確定要刪除這筆員工資料嗎 ??</h4>
                    <table class="table">
                        <tr>
                            <td>姓名</td>
                            <td>@emp.Name</td>
                        </tr>
                        <tr>
                            <td>性別</td>
                            <td>@emp.Gender</td>
                        </tr>
                        <tr>
                            <td>部門</td>
                            <td>@emp.Department</td>
                        </tr>
                        <tr>
                            <td>城市</td>
                            <td>@emp.City</td>
                        </tr>
                    </table>
                </div>
                <div class="modal-footer">
                    <button class="btn btn-danger" onclick="@CloseModalYes">是</button>
                    <button class="btn btn-warning" onclick="@CloseModalNo">否</button>
                </div>
            </div>
        </div>
    </div>
}


@functions {
    int currentCount = 0;
    bool ShowDialog = false;
    string DeleteResult = "";

    public class Empolyee
    {
        public string Name { get; set; }
        public string Gender { get; set; }
        public string Department { get; set; }
        public string City { get; set; }
    }
    Empolyee emp = new Empolyee()
    {
        Name = "Vulcan Lee",
        Gender = "M",
        City = "Kaohsiung",
        Department = "IT"
    };

    void IncrementCount()
    {
        currentCount++;
        DeleteResult = "";

        if (currentCount % 2 == 1)
        {
            ShowDialog = true;
        }
    }

    void CloseModalYes()
    {
        ShowDialog = false;
        DeleteResult = "是的,刪除這筆員工資料";
    }

    void CloseModalNo()
    {
        ShowDialog = false;
        DeleteResult = "不,放棄刪除這筆員工資料";
    }
}

執行結果

現在,請執行這個專案,點選左邊側邊攔的 Counter 項目,接著在網頁中間來點選 Click me 這個按鈕,現在將會發現到,若 currentCount 這個變數為奇數的時候,網頁上將會出現了 刪除員工資料 這個對話窗
若在對話窗中點選 是 這個按鈕,則該對話窗將會消失,且網頁上會出現 是的,刪除這筆員工資料 文字內容
若在對話窗中點選 否 這個按鈕,則該對話窗將會消失,且網頁上會出現 不,放棄刪除這筆員工資料 文字內容




2018年12月2日 星期日

Blazor 3 使用事件聚合器來動態顯示或者隱藏控制練習

Blazor 3 使用事件聚合器來動態顯示或者隱藏控制練習

更多關於 Blazor 教學影片,可以參考 Blazor 教學影片播放清單 或者 Blazor 快速體驗教學影片撥放清單。也歡迎訂閱本 .NET / Blazor / Xamarin.Forms 影片頻道 。

當在使用 Blazor 開發框架進行開發的時候,將會設計許多的 元件 Component ,也就是網頁中的特定 UI 畫面,藉由組合這些 元件 就會形成整個網頁內容;然而,有些時候將會需要在某個 元件A 中進行操作的時候,想要變更其他 元件B 的顯示狀態,也許 元件B 是 元件A 的 父元件或者是 子元件,這個時候將會有幾個技術可以選擇。第一個就是透過 JavaScript 來變更網頁上的 DOM 項目 Element 的 屬相 Attribut 或者變更其 CSS 設定;另外就是直接使用 .NET C# 中的技術,不去使用 JavaScript 程式語言,這樣對於 .NET C# 的開發者而言,可以更佳的輕鬆、自在的使用自己所孰悉的技術。
在 .NET C# 開發環境下,想要完成這樣的需求,可以使用 委派 Delegate 或者 事件 Event,然而對於這兩個技術想要在 Blazor 開發環境下來使用,讓不同的階層的 元件 可以彼此溝通訊息,對於 委派 而言,可以透過元件參數傳遞委派到子元件內,而對於事件而言,開發者必須宣告一個靜態事件,透過這樣全域靜態方法,讓各個子元件可以訂閱與觸發特定的事件,但是,這樣的設計方式也是非常的不好,因為這個靜態事件會存在於整個應用程式生命週期內,若有個子元件訂閱了這個事件,並且該子元件不再使用到了,該子元件必須要解除訂閱這個事件,否則,該子元件物件是沒有辦法被 .NET CLR 資源回收 Garbage Collection GC (關於 GC 的內容,可以參考 記憶體回收的基本概念 ),並且會有記憶體洩漏 Memory Leak 的嚴重問題產生。
在這篇文章將會使用 事件聚合器 Event Aggregator 這個設計模式,提供各 子元件 間的通訊通知之用,在事件聚合器設計模式下,提供了 訂閱 Subscribe 事件與 發布 Publish 事件兩個方法,當使用者執行了 發布 特定事件的時候,所有 訂閱 該特定事件的物件,就可以執行其對應的程式碼。不過,在這裡將不會說明如何從無到有的設計出 事件聚合器 這樣的設計模式程式碼,因為,我們不需要為了要使用輪子,而去發明另外一個輪子;在這裡將會從 Prism 這個開發框架內,抽取出該 Prism 所設計的 事件聚合器程式碼,並且在這個範例專案中來使用。
使用 Prism 所提供的 事件聚合器 程式碼的好處是:可以使用相依性注入的方式來注入 IEventAggregator 的具體實作物件、對於所綁定特定事件的訂閱方法,採用的 弱式參考 WeakReference 的方式來訂閱,因此,當某個 子元件 在 .NET 環境下不被在使用的時候,不會因為該 子元件 內還有訂閱 事件聚合器 內的某個事件,而導致該 子元件 物件不會被 .NET CLR 資源回收 Garbage Collection GC ,這是因為採用的 弱式參考 架構來訂閱事件,所以,不再使用到的 子元件 還是會被 .NET CLR 資源回收 Garbage Collection 機制進行從記憶體內回收該物件所佔用的記憶體空間。
這個說明範例將會修改 Blazor 專案範本建立的專案,修正該網頁的最上方會有一個 Login 按鈕,當使用者在 Counter 元件中點選按鈕,且當時的計數器值為偶數的時候,Login 按鈕會隱藏起來,而 Logout 按鈕會顯示出來,反之若當時計數器值為奇數的時候,Login 按鈕便會顯示出來,Logout 按鈕就會隱藏起來;而在這裏的顯示與隱藏功能,將會使用 Bootstrap 4 內宣告的 collapse 來實作出來, 本篇文章的範例原始碼,可以從 BlazorEventAggregator 取得。

建立測試專案

現在可以開始建立第一個 Blazor 開發專案。
  • 啟動 Visual Studio 2017
  • 點選功能表的 [檔案] > [新增] > [專案] 功能表選項
  • 在 [新增專案] 對話窗中左邊區域,選擇 [已安裝] > [Visual C#] > [Web] > [ASP.NET Core Web 應用程式]
  • 在對話窗的下方的 [名稱] 欄位中,輸入這個練習專案的名稱 BlazorEventAggregator
  • 在對話窗的下方的 [位置] 欄位中,選擇這個專案要儲存的檔案路徑
  • 最後點選對話窗的右下方 [確定] 按鈕
  • 在 [新增 ASP.NET Core Web 應用程式] 對話窗左上方區域,在第一個下拉選單,選擇 [.NET Core] 在第二個下拉選單,請選擇最新的 ASP.NET Core 版本,在現在這個時間點,可以選擇 [ASP.NET Core 2.1]
  • 在對話窗中間區域,請點選 [Blazor] 這個項目
  • 最後點選對話窗的右下方 [確定] 按鈕
  • 使用滑鼠右擊在最上方的方案節點,選擇 [加入] > [新增專案]
  • 在 [新增專案] 對話窗中,點選左方的 [已安裝] > [Visual C#]
  • 接著,在對話窗的中間,點選 [類別庫 .NET Standard]
  • 在對話窗下方的名稱欄位,輸入 EventAggreators ,最後點選 [確定] 按鈕,完成建立這個 .NET Standard 類別庫
  • 請將 BlazorEventAggregator 這個 Github Repository 內專案名稱為 EventAggreators 下的 Events 目錄,複製到剛剛建立的 EventAggreators 專案下。
  • 滑鼠右擊 BlazorEventAggregator 專案內的 [相依性] 節點,選擇 [加入參考]
  • 當 [參考管理員] 對話窗出現之後,點選左方的 [專案] 節點,在勾選中間的 EventAggregators 組件名稱
  • 點選 [確定] 按鈕
  • 底下是完成後的專案架構

進行 Prism 事件聚合器的 DI 容器註冊

當使用 事件聚合器 的時候,在這個專案內需要有個全域的 事件聚合器 物件,這樣才能夠讓各個 子元件 來進行訂閱特定事件的需求;在 Blazor 專案內,將會使用 IoC 容器 Container 機制進行 事件聚合器 介面與具體實作類別的註冊,而在每個 子元件 若要透過 事件聚合器 進行特定事件的訂閱或者發布的時候,就可以注入 IEventAggregator 這個介面,便可以取得 Prism 事件聚合器 的實作物件。
  • 打開專案內的 [StartUp.cs] 檔案
  • 找到 [ConfigureServices] 方法,使用 AddSingleton 方法來進行註冊,這裡可以使用 services.AddSingleton<IEventAggregator, EventAggregator>(); 這個方法。
 Startup.cs
public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<IEventAggregator, EventAggregator>();
    }
    public void Configure(IBlazorApplicationBuilder app)
    {
        app.AddComponent<App>("app");
    }
}

建立 事件聚合器 會用到的 事件資料模型

接下來要建立兩個 事件聚合器 的事件 ShowLoginEvent 與 ShowLogoutEvent 兩個類別,這兩個類別都需要繼承 PubSubEvent 這個類別,其中泛型型別的 T 為該特定事件發布與觸發的時候,所要傳送與接收的資料型別。
  • 滑鼠右擊 BlazorEventAggregator 專案節點,選擇 [加入] > [新增資料夾],並且輸入 [Models] 資料夾名稱
  • 建立 ShowLoginEvent 事件類別
    • 滑鼠右擊 [Models] 資料夾節點,選擇 [加入] > [類別]
    • 在 [新增項目] 對話窗中,點選 [已安裝] > [ASP.NET Core] > [密碼] > [類別] 選項,接著,在下方名稱欄位,輸入 ShowLoginEvent.cs ,最後點選右下方的 [新增] 按鈕
  • 將底下程式碼輸入到剛剛建立的 ShowLoginEvent 類別內
 Models > ShowLoginEvent.cs
public class ShowLoginEvent : PubSubEvent<ShowLoginEventPayload>
{
}
public class ShowLoginEventPayload
{
    public bool IsShow { get; set; }
}
  • 建立 ShowLogoutEvent 事件類別
    • 滑鼠右擊 [Models] 資料夾節點,選擇 [加入] > [類別]
    • 在 [新增項目] 對話窗中,點選 [已安裝] > [ASP.NET Core] > [密碼] > [類別] 選項,接著,在下方名稱欄位,輸入 ShowLogoutEvent.cs ,最後點選右下方的 [新增] 按鈕
  • 將底下程式碼輸入到剛剛建立的 ShowLogoutEvent 類別內
 Models > ShowLogoutEvent.cs
public class ShowLogoutEvent : PubSubEvent<ShowLogoutEventPayload>
{
}
public class ShowLogoutEventPayload
{
    public bool IsShow { get; set; }
}

修正網頁共用版型元件

在這裡將會要在網頁的最上方加入兩個按鈕: Login 與 Logout ,整個網頁在一啟動的時候,將只會顯示 Login 按鈕,而 Logout 按鈕將會收起隱藏起來,這裡將會透過 單向資料綁定 功能,在這裡兩個按鈕上分別使用 @ShowLogin 與 @ShowLogout 在 class 屬性上,進而來綁定 .NET C# 中的 ShowLogin / ShowLogout 這兩個變數。因此,當想要顯示某個 DOM 項目的時候,僅需要把特定變數的字串值設定為空字串,若要隱藏某個 DOM 項目 Element 的時候,便可以設定特定變數的字串值為 collapse。
那麼,要在哪個地方來進行變更特定 DOM 項目的顯示與隱藏的變數值設定呢?此時,先要宣告這個 元件 需要自動注入 IEventAggregator 這個 事件聚合器 物件,因此,在最上方使用 @inject IEventAggregator eventAggregator 陳述式,這樣,在這個元件內就可以使用 eventAggregator 這個變數來操作 Prism 的事件聚合器;而在接下來的設計過程,將會需要使用到剛剛建立的兩個事件類別,因此,使用 @using BlazorEventAggregator.Models 陳述式,宣告這個元件可以使用 BlazorEventAggregator.Models 命名空間內的型別。
最後,在這個元件內需要進行 事件 訂閱 的設計,也就是當其他元件要把登入按鈕隱藏起來,並且顯示登出按鈕,在這個訂閱事件內便可以處理這些需求,那麼,該在哪裡設計這樣的需球,這個時候需要 覆寫 override OnInit 這個方法,並且在這個方法內進行使用 事件聚合器 來訂閱特定事件的委派方法。
當要使用事件聚合器來訂閱特定事件,可以使用事件聚合器物件的 GetEvent 泛型方法,取得 特定事件型別,接著就可以使用 Subscribe 這個方法來指定一個委派方法,例如,eventAggregator.GetEvent<ShowLoginEvent>().Subscribe 這個敘述,將會使用事件聚合器物件,來進行 ShowLoginEvent 事件的訂閱。
最後,就可以在委派的訂閱事件方法內,根據使用者使用 Publish 方法所傳送過來的狀態物件,進行設定 ShowLogin 或者 ShowLogout 變數值,不過,最後一定需要執行 base.StateHasChanged(); 方法,這樣 ShowLogin 或者 ShowLogout 變數值 就會透單向資料綁定更新到網頁的 DOM 上了。關於更多關於 StateHasChanged 的說明,可以參考 Class BlazorComponent
現在,請依照底下說明來修正專案程式碼
  • 請打開 [Shared] 資料夾內的 [MainLayout.cshtml] 檔案
  • 使用底下程式碼替換掉 [MainLayout.cshtml] 檔案內容
 Shared > MainLayout.cshtml
@inherits BlazorLayoutComponent
@using Prism.Events
@using BlazorEventAggregator.Models
@inject IEventAggregator eventAggregator

<div class="sidebar">
    <NavMenu />
</div>

<div class="main">
    <div class="top-row px-8">
        <button class="btn btn-primary @ShowLogin">Login</button>
        <button class="btn btn-warning @ShowLogout">Logout</button>
        <a href="http://blazor.net" target="_blank" class="ml-md-auto">About</a>
    </div>

    <div class="content px-4">
        @Body
    </div>
</div>

@functions
{
    string ShowLogin = "";
    string ShowLogout = "collapse";

    protected override void OnInit()
    {
        eventAggregator.GetEvent<ShowLoginEvent>().Subscribe(x =>
        {
            if (x.IsShow == true)
            {
                ShowLogin = "";
            }
            else
            {
                ShowLogin = "collapse";
            }
            base.StateHasChanged();
        });

        eventAggregator.GetEvent<ShowLogoutEvent>().Subscribe(x =>
        {
            if (x.IsShow == true)
            {
                ShowLogout = "";
            }
            else
            {
                ShowLogout = "collapse";
            }
        });
        base.StateHasChanged();
    }
}

修正 Counter 元件,發佈特定事件通知

現在將會要來修正 Counter 元件,當使用者在 Counter 元件中點選按鈕,且當時的計數器值為偶數的時候,Login 按鈕會隱藏起來,而 Logout 按鈕會顯示出來,反之若當時計數器值為奇數的時候,Login 按鈕便會顯示出來,Logout 按鈕就會隱藏起來;而在這裏的顯示與隱藏功能。現在,先在該元件的最上方加入 @inject IEventAggregator eventAggregator 表示要注入 事件聚合器 物件與 @using BlazorEventAggregator.Models表示要參考 BlazorEventAggregator.Models 命名空間。
在按鈕事件 IncrementCount 中,判斷 currentCount 這個整數變數值為單數或者是偶數,接著可以使用 eventAggregator.GetEvent<ShowLoginEvent>().Publish 與 eventAggregator.GetEvent<ShowLogoutEvent>().Publish 方法,分別對 事件聚合器 物件送出兩個事件通知,這樣,只要有透過該 事件聚合器 物件訂閱的方法,就會被觸發執行了。
現在,請依照底下說明來修正專案程式碼
  • 請打開 [Pages] 資料夾內的 [Counter.cshtml] 檔案
  • 使用底下程式碼替換掉 [Counter.cshtml] 檔案內容
 Pages > Counter.cshtml
@page "/counter"
@using Prism.Events
@using BlazorEventAggregator.Models
@inject IEventAggregator eventAggregator

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" onclick="@IncrementCount">Click me</button>

@functions {
    int currentCount = 0;

    void IncrementCount()
    {
        currentCount++;

        if (currentCount % 2 == 0)
        {
            eventAggregator.GetEvent<ShowLoginEvent>().Publish(new ShowLoginEventPayload()
            {
                IsShow = true
            });
            eventAggregator.GetEvent<ShowLogoutEvent>().Publish(new ShowLogoutEventPayload()
            {
                IsShow = false
            });
        }
        else
        {
            eventAggregator.GetEvent<ShowLoginEvent>().Publish(new ShowLoginEventPayload()
            {
                IsShow = false
            });
            eventAggregator.GetEvent<ShowLogoutEvent>().Publish(new ShowLogoutEventPayload()
            {
                IsShow = true
            });
        }
    }
}

執行結果

現在,請執行這個專案,點選左邊側邊攔的 Counter 項目,接著在網頁中間來點選 Click me 這個按鈕,現在將會發現到,若 currentCount 這個變數為偶數的時候,上方的僅會出現 Login 按鈕
反之,若 currentCount 這個變數為奇數的時候,上方的僅會出現 Logout 按鈕



2018年11月23日 星期五

Blazor 2 HTML Element 動態顯示或者隱藏的控制練習

Blazor 2 HTML Element 動態顯示或者隱藏的控制練習

更多關於 Blazor 教學影片,可以參考 Blazor 教學影片播放清單 或者 Blazor 快速體驗教學影片撥放清單。也歡迎訂閱本 .NET / Blazor / Xamarin.Forms 影片頻道 。

Blazor 開發框架下有個非常好用的功能,那就是 資料綁定 Data Binding 機制,這個機制可以做到當在一個 Blazor 元件 Component 內宣告一個欄位變數,例如該欄位名稱為 MyField ,則可以在 HTML 標記 Markup 中使用 @ 加上這個欄位名稱,便可以將這個欄位變數值與 HTML 標記整合再一起;而在這個練習中,想要設計一個元件,該元件上有個按鈕,當按下這個按鈕之後,該元件上的網頁部分內容將會隱藏起來,若再度點選一次這個按鈕,則剛剛隱藏的內容又會顯示出來。如同大家對於網頁設計的了解,在這裡將會透過 HTML DOM display 屬性來控制網頁上的 HTML Element 是否要顯示還是隱藏,不過,更為重要的是,這裡所說明的所有處理過程,都不會用到任何一行 JavaScript ,只需要透過 .NET C# 程式碼就可以做到,這就是 Blazor 好用的地方。本篇文章的範例原始碼,可以從 BlazorElementVisibility 取得。

建立測試專案

若已經將 Blazor 開發工具安裝與設定完成之後,現在可以開始建立第一個 Blazor 開發專案。
  • 啟動 Visual Studio 2017
  • 點選功能表的 [檔案] > [新增] > [專案] 功能表選項
  • 在 [新增專案] 對話窗中左邊區域,選擇 [已安裝] > [Visual C#] > [Web] > [ASP.NET Core Web 應用程式]
  • 在對話窗的下方的 [名稱] 欄位中,輸入這個練習專案的名稱 BlazorElementVisibility
  • 在對話窗的下方的 [位置] 欄位中,選擇這個專案要儲存的檔案路徑
  • 最後點選對話窗的右下方 [確定] 按鈕
  • 在 [新增 ASP.NET Core Web 應用程式] 對話窗左上方區域,在第一個下拉選單,選擇 [.NET Core] 在第二個下拉選單,請選擇最新的 ASP.NET Core 版本,在現在這個時間點,可以選擇 [ASP.NET Core 2.1]
  • 在對話窗中間區域,請點選 [Blazor] 這個項目
  • 最後點選對話窗的右下方 [確定] 按鈕

練習步驟

接下來將要建立一個元件 Component,在這個元件中將會使用 div 標籤 (Tag) ,在裡面會有8個按鈕顯示在畫面上。在最後面會有一個 切換顯示狀態 按鈕,當點選這個按鈕之後,剛剛 div 標籤內的8個按鈕就會消失不見,若再度點選 切換顯示狀態 按鈕,則這8個按鈕就會再度出現。
  • 建立一個名為 EleVisible 的 Razor 檢視檔案
    • 在 [Pages] 資料夾使用滑鼠右擊,選擇 [加入] > [新增項目]
    • 在 [新增項目] 對話窗中,點選 [已安裝] > [ASP.NET Core] > [Razor 頁面] 選項,接著,在下方名稱欄位,輸入 EleVisible.cshtml ,最後點選右下方的 [新增] 按鈕
  • 將 EleVisible.cshtml 檔案使用底下 Razor 頁面的 HTML 宣告與 C# 成程式碼來替換
 Pages > EleVisible.cshtml
@page "/ElementVisibility"

<h1>HTML Element 動態顯示或者隱藏的控制練習</h1>

<p>練習步驟</p>
<p>建立一個名為 EleVisible 的 Razor 檢視檔案</p>
<p>使用 ShowAction 字串變數來控制 style display 的值</p>
<p>綁定按鈕事件,動態的切換 ShowAction 字串內容,造成 HTML 項目可以動態的顯示或者隱藏</p>
<p>修正 NavMenu 元件 Component,使其可以顯示這個 Blazor 元件在網頁上</p>

<hr />

<div style="display: @ShowAction">
    <button type="button" class="btn btn-primary">Primary</button>
    <button type="button" class="btn btn-secondary">Secondary</button>
    <button type="button" class="btn btn-success">Success</button>
    <button type="button" class="btn btn-danger">Danger</button>
    <button type="button" class="btn btn-warning">Warning</button>
    <button type="button" class="btn btn-info">Info</button>
    <button type="button" class="btn btn-light">Light</button>
    <button type="button" class="btn btn-dark">Dark</button>
</div>

<hr />

<button class="btn btn-primary" onclick="@ChangeStatus">切換顯示狀態</button>

<hr />

<div>ShowAction = @ShowAction</div>

@functions {
bool IsShow = true;
string ShowAction = "";
void ChangeStatus()
{
    IsShow = !IsShow;
    ChangeShowMode();
}

void ChangeShowMode()
{
    if (IsShow == true)
    {
        ShowAction = "";
    }
    else
    {
        ShowAction = "none";
    }
}
}
  • 在 [Shared] 資料夾內,找到 [NavMenu.cshtml] Razor 檔案,接著將底下 HTML 標記宣告內容,加入到 <ul class="nav flex-column"> 內。
 Pages > EleVisible.cshtml
@page "/ElementVisibility"

<h1>HTML Element 動態顯示或者隱藏的控制練習</h1>

<p>練習步驟</p>
<p>建立一個名為 EleVisible 的 Razor 檢視檔案</p>
<p>使用 ShowAction 字串變數來控制 style display 的值</p>
<p>綁定按鈕事件,動態的切換 ShowAction 字串內容,造成 HTML 項目可以動態的顯示或者隱藏</p>
<p>修正 NavMenu 元件 Component,使其可以顯示這個 Blazor 元件在網頁上</p>

<hr />

<div style="display: @ShowAction">
    <button type="button" class="btn btn-primary">Primary</button>
    <button type="button" class="btn btn-secondary">Secondary</button>
    <button type="button" class="btn btn-success">Success</button>
    <button type="button" class="btn btn-danger">Danger</button>
    <button type="button" class="btn btn-warning">Warning</button>
    <button type="button" class="btn btn-info">Info</button>
    <button type="button" class="btn btn-light">Light</button>
    <button type="button" class="btn btn-dark">Dark</button>
</div>

<hr />

<button class="btn btn-primary" onclick="@IncrementCount">切換顯示狀態</button>

<hr />

<div>ShowAction = @ShowAction</div>

@functions {
bool IsShow = true;
string ShowAction = "";
void IncrementCount()
{
    IsShow = !IsShow;
    ChangeShowMode();
}

void ChangeShowMode()
{
    if (IsShow == true)
    {
        ShowAction = "";
    }
    else
    {
        ShowAction = "none";
    }
}
}
 Shared > NavMenu.cshtml
<li class="nav-item px-3">
    <NavLink class="nav-link" href="ElementVisibility">
        <span class="oi oi-list-rich" aria-hidden="true"></span> Element Visibility
    </NavLink>
</li>

EleVisible.cshtml 設計說明

在這個 EleVisible.cshtml Razor 檔案內,將會看到 <div style="display: @ShowAction"> 這樣的宣告,而對於 DOM 的 Style display 屬性值將會由 C# 中的 ShowAction 欄位值來提供;在 Blazor 中,當把一個變數宣告到 HTML 語言中來使用的時候,將會預設採用單向資料綁定機制來運作,也就是說,當 ShowAction 這個欄位值有變更的話,此時,在 DOM 的 Style display 屬性值也會跟著進行更新。
當使用者點選了 切換顯示狀態 按鈕,將會觸發 ChangeStatus 按鈕事件,這是因為在 HTML 中,使用了 <button class="btn btn-primary" onclick="@ChangeStatus"> 宣告。而在 ChangeStatus 按鈕事件內,將會判對當時的 ShowAction 是否為 空字串,若為空字串,此時, div 標籤內的內容將會顯示出來,並且將該 ShowAction 欄位值為 "none",這樣就會造成 div 標籤內的這些按鈕將會隱藏在網頁上;反之,若 ShowAction 的值為"none",當按按鈕事件又被觸發的話,ShowAction 的值就會設定為空字串,這樣 div 標籤內的這些按鈕又會顯示出來了。
因為 WebAssembly 內的 C# 程式碼無法直接存取網頁內的 DOM,所以,將會透 Blazor 提供的 JavaScript Rendering 來幫助進行存取網頁 DOM 內容,因此,當 ShowAction 屬性值有變動的時候,將會透過 Blazor 建立的 Render Tree 呈現樹,透過 Render Tree Rendering 來將 C# 內最新的單向綁定的屬性值,透過 Blazor 提供的 JavaScript 更新到網頁上的 DOM,也就會更新 DOM 中的標籤內的 CSS 屬性值。

執行結果

現在,請執行這個專案,將會在網頁上看如下圖的畫面,此時可以看到有8個按鈕顯示在網頁上
當按下 切換顯示狀態 按鈕,將會看到這8個按鈕就會隱藏起來了