2020年4月10日 星期五

Blazor 綁定屬性變更 Part 3 - 透過 PropertyChanged.Fody 套件,使用 INotifyPropertyChanged 機制,簡化程式碼設計

Blazor 綁定屬性變更 Part 3 - 透過 PropertyChanged.Fody 套件,使用 INotifyPropertyChanged 機制,簡化程式碼設計

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

Blazor 綁定屬性變更 Part 3 - 透過 PropertyChanged.Fody 套件,使用 INotifyPropertyChanged 機制,簡化程式碼設計
這是本系列文章的第三個部分,在前一篇文章使用 INotifyPropertyChanged 提供介面,針對要使用的資料模型,都需要進行實作出 INotifyPropertyChanged 介面,可是,這樣會造成該類別內的屬性,都需要使用 含有支援欄位的屬性 的設計方式,而且在設定存取子 Set Accessor 的部分,也需要增加額外的程式碼來進行拋出 PropertyChanged 的事件;對於這樣的設計方式會顯得有些繁雜而且容易出錯。
因此,在這篇文章中,將會使用另一種做法,那就是使用 PropertyChanged.Fody 這個套件,將許多繁雜的程式碼,透過這個套件來交由編譯器來產生出來;另外,該套件也提供了許多額外好用的機制,On_PropertyName_Changed 就是一個,只要依照該套件規範的方式來設計,當指定的屬性值有變更的時候,就會自動觸發與執行這個方法。
這個說明專案的原始碼位於 bzINPCbyFody

建立 Blazor Server-Side 的專案

首先,還是先來建立一個新的專案
  • 打開 Visual Studio 2019
  • 點選右下方的 [建立新的專案] 按鈕
  • [建立新專案] 對話窗將會顯示在螢幕上
  • 從[建立新專案] 對話窗的中間區域,找到 [Blazor 應用程式] 這個專案樣板選項,並且選擇這個項目
  • 點選右下角的 [下一步] 按鈕
  • 現在 [設定新的專案] 對話窗將會出現
  • 請在這個對話窗內,輸入適當的 [專案名稱] 、 [位置] 、 [解決方案名稱]
    在這裡請輸入 [專案名稱] 為 bzINPCbyFody
  • 完成後,請點選 [建立] 按鈕
  • 當出現 [建立新的 Blazor 應用程式] 對話窗的時候
  • 請選擇最新版本的 .NET Core 與 [Blazor 伺服器應用程式]
  • 完成後,請點選 [建立] 按鈕
稍微等會一段時間,Blazor 專案將會建立起來

安裝 PropertyChanged.Fody NuGet 套件

  • 滑鼠右擊 [相依性] 節點
  • 選擇 [管理 NuGet 套件]
  • 在 [管理 NuGet 套件] 視窗內,點選 [瀏覽] 標籤頁次
  • 搜尋 PropertyChanged.Fody 這個套件
  • 找到這個套件,點選 [安裝] 按鈕,將這個套件安裝起來

建立需求網頁 Balzor 元件

  • 打開 [Pages] 資料夾內的 [Index.razor] 檔案
  • 使用底下 Razor 元件標記與程式碼,替換該檔案內的原有內容
@page "/"

<h1>在 Blazor 透過 PropertyChanged.Fody 套件,使用 INotifyPropertyChanged 事件,設計屬性變更的需求</h1>
<div class="form-group">
    <label for="FirstName">名</label>
    <input id="FirstName" class="form-control" @bind="MyPerson.FirstName" />
</div>
<div class="form-group">
    <label for="LastName">姓</label>
    <input id="LastName" class="form-control" @bind="MyPerson.LastName" />
</div>
<div class="form-group">
    <label for="Age">年紀</label>
    <input type="number" id="Age" class="form-control"
           @bind="MyPerson.Age" @bind:event="oninput" />
</div>

<button type="submit" class="btn btn-primary" disabled="@MyPerson.IsDisabled">Submit</button>

<div class="text-danger">
    @MyPerson.Age
</div>
<div class="text-danger">
    @MyPerson.AgeRange
</div>

@code{
    class Person : System.ComponentModel.INotifyPropertyChanged
    {
        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Age { get; set; }
        public string AgeRange { get; set; }
        public bool IsDisabled { get; set; } = true;

        public void OnAgeChanged()
        {
            if (Age < 13)
            {
                AgeRange = "你是小朋友";
                IsDisabled = true;
            }
            else if (Age < 20)
            {
                AgeRange = "你是年青人";
                IsDisabled = false;
            }
            else if (Age < 28)
            {
                AgeRange = "你是青年人";
                IsDisabled = false;
            }
            else
            {
                AgeRange = "你是成年人";
                IsDisabled = false;
            }
        }
    }

    Person MyPerson = new Person();
}
在這個 index.razor 檔案內,對於 HTML 標記的設計上,原則上沒有使用到任何宣告,如同上一篇文章所提到的內容。
不過,在這裡將會針對 Person 類別,同樣也實作了 INotifyPropertyChanged 這個介面,不過,所有的屬性,將會使用 自動實作屬性 來完成,不過,這裡將會產生疑問,那就是當屬性值有異動的時候,要如何觸發 PropertyChanged 這個事件呢?
還記得剛剛之前有安裝了 PropertyChanged.Fody 這個套件,只要建置專案,對於剛剛所需要處理的程式碼,這個套件將會幫忙產生其他會用到的程式碼。
使用這樣的設計方式,有點像是在設計 ViewModel,將會把許多與頁面有關的程式碼,都寫到這個類別內,不過,透過了資料綁定機制,形成鬆散耦合的關係;另外,這裡也會使用 PropertyChanged.Fody 套件提供的功能,可以撰寫一個屬性變更的 callback 函式,也就是說,當屬性值有變動的時候,會自動執行的方法。
想要使用這樣的功能,僅需要使用特定的方法簽章來命名即可, PropertyChanged.Fody 套件會自動完成其他相關程式碼運作機制。例如,想要針對當 Age 屬性有異動的時候,可以自動執行某個方法,這裡需要使用這樣的方法簽章來命名
public void On_PropertyName_Changed(){...}
其中,對於方法名稱的最前面需要有 On 這個字串,緊接著是這個屬性的名稱,最後使用 Changed 最為結尾,一旦設計出這個方法之後,只要 Age 的屬性有異動的時候,將會自動執行 OnAgeChanged 這個方法。
現在,這個專案設計工作已經完成了,現在可以來比對這三種的不同作法,將會發現到這裏所提出的作法,所設計出來的程式碼最為簡單與清爽,而且還增加了許多不錯的功能可以來應用。
底下將會是執行結果









2020年4月9日 星期四

Blazor 綁定屬性變更 Part 2 - 實作 PropertyChanged 機制,用來偵測有興趣的物件有變化時,需要作出相對應的處理機制

Blazor 綁定屬性變更 Part 2 - 實作 PropertyChanged 機制,用來偵測有興趣的物件有變化時,需要作出相對應的處理機制

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

Blazor 綁定屬性變更 Part 2 - 實作 PropertyChanged 機制,用來偵測有興趣的物件有變化時,需要作出相對應的處理機制
這是本系列文章的第二個部分,在前一篇文章使用 DOM 提供的事件,綁定到 .NET C# 元件內的委派方法內 (這樣的開發過程將完全沒有使用到任何 JavaScript 程式碼,便可以完成這樣的設計,這也是 Blazor 開發框架最大的特色與好處),進行當年紀屬性值有異動的時候,可以根據當前使用者輸入的年紀屬性值,進行相關商業邏輯計算工作。
在這篇文章中,將會使用另為一個機制,也就是在 MVVM 設計模式內經常會使用到 INotifyPropertyChanged 介面 (這個介面自從 .NET Framework 2.0 就已經存在了,在 Person 類別內來實作出 PropertyChanged 功能,用來做到 通知用戶端已變更屬性值。
這個說明專案的原始碼位於 bzINPC

建立 Blazor Server-Side 的專案

首先,還是先來建立一個新的專案
  • 打開 Visual Studio 2019
  • 點選右下方的 [建立新的專案] 按鈕
  • [建立新專案] 對話窗將會顯示在螢幕上
  • 從[建立新專案] 對話窗的中間區域,找到 [Blazor 應用程式] 這個專案樣板選項,並且選擇這個項目
  • 點選右下角的 [下一步] 按鈕
  • 現在 [設定新的專案] 對話窗將會出現
  • 請在這個對話窗內,輸入適當的 [專案名稱] 、 [位置] 、 [解決方案名稱]
    在這裡請輸入 [專案名稱] 為 bzINPC
  • 完成後,請點選 [建立] 按鈕
  • 當出現 [建立新的 Blazor 應用程式] 對話窗的時候
  • 請選擇最新版本的 .NET Core 與 [Blazor 伺服器應用程式]
  • 完成後,請點選 [建立] 按鈕
稍微等會一段時間,Blazor 專案將會建立起來

建立有實作 INotifyPropertyChanged 的 Person 類別

  • 滑鼠右擊專案中的 [Pages] 資料夾節點
  • 點選 [加入] > [類別]
  • 現在 [新增項目] 對話窗將會出現
  • 現在預設的新增項目將會選擇為 [類別]
  • 在下方 [名稱] 欄位中,輸入 Person
  • 點選右下方的 [新增] 按鈕
  • 使用底下 C# 程式碼,替換該檔案內的原有內容
namespace bzINPC.Pages
{
    public class Person : System.ComponentModel.INotifyPropertyChanged
    {
        private string firstName;

        public string FirstName
        {
            get { return firstName; }
            set
            {
                if (firstName != null && firstName != value)
                {
                    firstName = value;
                    OnPropertyChanged();
                }
            }
        }

        private string lastName;

        public string LastName
        {
            get { return lastName; }
            set
            {
                if (lastName != null && lastName != value)
                {
                    lastName = value;
                    OnPropertyChanged();
                }
            }
        }

        private int age;

        public int Age
        {
            get { return age; }
            set
            {
                if (age != value)
                {
                    age = value;
                    OnPropertyChanged();
                }
            }
        }

        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

        void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName]string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
        }
    }
}
在這個 Person 類別內,將會實作了 System.ComponentModel.INotifyPropertyChanged 介面,因此,將會多了一行 public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; 宣告敘述。
在這個類別中,有兩個設計重點,第一個是要設計出一個 OnPropertyChanged 方法,這個方法將會於當該 Person 類別內的屬性有變動的時候,將會觸發 PropertyChanged 這個事件;而只要有訂閱這個 Person 執行個體的 PropertyChanged 事件,對於該類別內的任何屬性有異動的時候,都會收到觸發事件的通知。
第二個就是原先該類別內的相關屬性,都是使用 自動實作屬性 來設計,這裡為了要能夠做到當屬性值有異動的時候,可以拋出相關事件,因此,需要改成 含有支援欄位的屬性 這樣的設計。
因此,對於每個類別內的屬性成員,都會類似有底下的設計
這裡將會使用 Age 這個屬性設計來說明,對於設定存取子,首先將會檢查現在新變更的屬性值,與原先的屬性值是否相同,若為不相同,則將最新的屬性值設定給該屬性持有的欄位,接著,呼叫 OnPropertyChanged() 方法,因此,將會發出一個事件,在該事件將會註明 Age 這個屬性已經有異動了。
private int age;
public int Age
{
    get { return age; }
    set
    {
        if (age != value)
        {
            age = value;
            OnPropertyChanged();
        }
    }
}

建立需求網頁 Balzor 元件

  • 打開 [Pages] 資料夾內的 [Index.razor] 檔案
  • 使用底下 Razor 元件標記與程式碼,替換該檔案內的原有內容
@page "/"

<h1>在 Blazor 使用 INotifyPropertyChanged 事件,設計屬性變更的需求</h1>
<div class="form-group">
    <label for="FirstName">名</label>
    <input id="FirstName" class="form-control" @bind="MyPerson.FirstName" />
</div>
<div class="form-group">
    <label for="LastName">姓</label>
    <input id="LastName" class="form-control" @bind="MyPerson.LastName" />
</div>
<div class="form-group">
    <label for="Age">年紀</label>
    <div class="form-group">
        <label for="Age">年紀</label>
        <input type="number" id="Age" class="form-control"
               @bind="MyPerson.Age" @bind:event="oninput" />
    </div>
</div>

<button type="submit" class="btn btn-primary" disabled="@IsDisabled">Submit</button>

<div class="text-danger">
    @MyPerson.Age
</div>
<div class="text-info">
    @Message
</div>
<div class="text-danger">
    @AgeRange
</div>

@code{
    Person MyPerson = new Person();
    bool IsDisabled = true;
    string AgeRange = "";
    string Message = "";

    protected override void OnInitialized()
    {
        MyPerson.PropertyChanged += (s, e) =>
        {
            Message = $"這個屬性 {e.PropertyName} 已經有變更了";
            if (e.PropertyName == nameof(MyPerson.Age))
            {
                AgeChanged();
            }
        };
    }

    void AgeChanged()
    {
        if (MyPerson.Age < 13)
        {
            AgeRange = "你是小朋友";
            IsDisabled = true;
        }
        else if (MyPerson.Age < 20)
        {
            AgeRange = "你是年青人";
            IsDisabled = false;
        }
        else if (MyPerson.Age < 28)
        {
            AgeRange = "你是青年人";
            IsDisabled = false;
        }
        else
        {
            AgeRange = "你是成年人";
            IsDisabled = false;
        }
        StateHasChanged();
    }
}
在這個 index.razor 檔案內,對於 HTML 標記的設計上,原則上沒有使用到任何宣告,用來綁定 C# 的委派方法內,例如,對於年紀輸入的標記中,將會使用這樣的宣告 <input type="number" id="Age" class="form-control" @bind="MyPerson.Age" @bind:event="oninput" /> 。從這樣的 HTML 宣告中,可以看到,對於這個 input 標籤中,使用 @bind="MyPerson.Age" 來宣告使用雙向資料綁定 two-way data binding,而又使用了 @bind:event="oninput" 的指示詞 (directive) 用來宣告當使用者有輸入任何資料之後,就需要立即透過資料綁定機制,把使用者輸入的內容,更新到 .NET C# 內的 MyPerson.Age 屬性上。
在這裡也使用了 Blazor 生命週期 - 元件初始化方法 ,也就是 OnInitialized 這個方法,在此訂閱該 MyPerson 物件中的屬性有異動的時候,將會需要接收的事件委派方法,這裡可以參考底下的程式碼。
protected override void OnInitialized()
{
    MyPerson.PropertyChanged += (s, e) =>
    {
        Message = $"這個屬性 {e.PropertyName} 已經有變更了";
        if (e.PropertyName == nameof(MyPerson.Age))
        {
            AgeChanged();
        }
    };
}
因為這個 MyPerson 執行個體的型別為 Person,而 Person 這個類別有實作 INotifyPropertyChanged,因此,對於 MyPerson 物件將會有 PropertyChanged 這個事件;在這個元件第一次建立的時候,將會使用 Lambda 匿名委派方法來訂閱這個事件,也就是說,當 MyPerson 這個物件中的屬性值有異動的時候,將會觸發執行這個匿名 Lambda 委派方法。
在這個 PropertyChanged 訂閱委派方法內,將會透過 Message 欄位將這次觸發的屬性名稱顯示在網頁上,接著判斷現在觸發的屬性名稱是否為 Age,若為 Age,則會進行有關年紀的商業邏輯計算的工作,也就是根據年紀顯示這是什麼類型的人並且決定按鈕是否要被停用還是啟用。
底下將會是執行結果






2020年4月8日 星期三

Blazor 綁定屬性變更 Part 1 - 透過 DOM 事件機制,用來偵測有興趣的物件有變化時,需要作出相對應的處理機制

Blazor 綁定屬性變更 Part 1 - 透過 DOM 事件機制,用來偵測有興趣的物件有變化時,需要作出相對應的處理機制

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

Blazor 綁定屬性變更 Part 1 - 透過 DOM 事件機制,用來偵測有興趣的物件有變化時,需要作出相對應的處理機制
這是 Blazor 綁定屬性變更問題需求探討的系列文章第一篇,首先,先來說明這系列文章想要設計出來的執行效果。當專案執行起來,將會想要出現底下畫面,在這裡共會有三個欄位 First Name 名 , Last Name 姓 , Age 年紀 ,其中前兩個為文字型態的內容,而年紀這個欄位,將會為 整數 數值。
當使用者在輸入年紀的時候,希望能夠即時在最下方顯示出相關文字,底下是要顯示文字的規則
  • 若年紀小於 13 ,將會顯示 你是小朋友
  • 若年紀小於 13 ,將會顯示 你是年青人
  • 若年紀小於 13 ,將會顯示 你是青年人
  • 否則 ,將會顯示 你是成年人
另外,還有一個需求,那就是當所輸入的 年紀 值小於 13 歲,則最下方的按鈕將會停用,無法點選,若年紀大於 13 歲,則可以點選
這個說明專案的原始碼位於 bzDOMEventChanged

建立 Blazor Server-Side 的專案

  • 打開 Visual Studio 2019
  • 點選右下方的 [建立新的專案] 按鈕
  • [建立新專案] 對話窗將會顯示在螢幕上
  • 從[建立新專案] 對話窗的中間區域,找到 [Blazor 應用程式] 這個專案樣板選項,並且選擇這個項目
  • 點選右下角的 [下一步] 按鈕
  • 現在 [設定新的專案] 對話窗將會出現
  • 請在這個對話窗內,輸入適當的 [專案名稱] 、 [位置] 、 [解決方案名稱]
    在這裡請輸入 [專案名稱] 為 bzDOMEventChanged
  • 完成後,請點選 [建立] 按鈕
  • 當出現 [建立新的 Blazor 應用程式] 對話窗的時候
  • 請選擇最新版本的 .NET Core 與 [Blazor 伺服器應用程式]
  • 完成後,請點選 [建立] 按鈕
稍微等會一段時間,Blazor 專案將會建立起來

建立需求網頁 Balzor 元件

在這裡,初步需求的設計程式碼與 HTML 標記,將會採用 Index.razor 這個檔案來設計,因此
  • 打開 [Pages] 資料夾內的 [Index.razor] 檔案
  • 使用底下 Razor 元件標記與程式碼,替換該檔案內的原有內容
@page "/"
@using System.ComponentModel.DataAnnotations

<h1>在 Blazor 使用 DOM 事件,設計屬性變更的需求</h1>

<div class="form-group">
    <label for="FirstName"></label>
    <input id="FirstName" class="form-control" @bind="MyPerson.FirstName" />
</div>
<div class="form-group">
    <label for="LastName"></label>
    <input id="LastName" class="form-control" @bind="MyPerson.LastName" />
</div>
<div class="form-group">
    <label for="Age">年紀</label>
    <input type="number" id="Age" class="form-control"
           @bind="MyPerson.Age" @bind:event="oninput" />
</div>

<button type="submit" class="btn btn-primary" disabled="@IsDisabled">Submit</button>

<div class="text-danger">
    @MyPerson.Age
</div>
<div class="text-danger">
    這裡可以顯示年紀分類說明文字
</div>

@code{

    class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Age { get; set; }
    }

    Person MyPerson = new Person();
    bool IsDisabled = true;
}
在這裡將會設計一個類別名為 Person ,可以讓使用者輸入 First Name , Last Name , Age 這三個屬性值;並且在這個 Blazor 元件中,使用敘述 Person MyPerson = new Person(); 建立一個 MyPerson 物件,該物件將會用於在 HTML 頁面中使用資料綁定 Razor 語法,來與 HTML 內的 DOM 元素進行綁定在一起。
在上面的標記與程式碼中,將可以看到,對於 Last Name , First Name , Age 這三個欄位,將會透過 Blazor Directive @bind 宣告使用 input 標記的雙向綁定,這裡分別使用了:@bind="MyPerson.FirstName" , @bind="MyPerson.LastName" , @bind="MyPerson.Age"
然而,對於 Age 這個欄位, 使用了 <input type="number" ... 宣告這裡要輸入的內容將會是一個數值,並且對於這個年紀欄位,由於需要即時偵測出使用者當時輸入了甚麼內容,而不是要等到使用者輸入完成之後,輸入焦點離開年紀欄位之後才會更新,所以,在這裡使用了 @bind:event="oninput" 這樣的語法來宣告要能夠即時更新使用輸入的內容到 .NET 物件, MyPerson.Age 欄位。
對於這個需求 [當所輸入的 年紀 值小於 13 歲,則最下方的按鈕將會停用,無法點選,若年紀大於 13 歲,則可以點選] ,在這裡將會使用 C# 宣告一個布林欄位 IsDisabled,並且將這個欄位使用單向綁定技術,綁定到按鈕的 disabled 的屬性值上。
現在,可以開始執行這個專案,並且在年紀欄位中,輸入任何的整數數值,但不用將輸入焦點離開這個欄位,就會看到底下紅色文字就會顯示出即時所輸入的文字內容。

建立解決問題之元件

雖然 Blazor 的資料綁定 Data Binding 機制,解決了可以將 .NET 的物件值與 HTML DOM 內的環境,綁定在一起現在要能解決這個問題,也就是說,透過了雙向綁定作法,若任何一方(來源 Source 或者目的 Target)的值有變動,將會即時更新到另外一方。
對於當使用者有輸入新的年紀數值的時候,此時,在 .NET 物件的 MyPerson.Age 屬性上屬性值,就已經透過 Blazor Two-way data binding 雙向綁定機制,自動把使用者輸入的最新數值,更新到 MyPerson.Age 值上;可是,此時對於在這個 Blazor 元件中的 C# 程式碼中,要如何知道 MyPerson.Age 的值已經有變動了,接下來,便需要針對當初提出的需求,進行設計:針對當前的年紀,顯示適當的文字與修正按鈕是否可以使用。
很多人對於這樣的需求想說,這裡可以使用 含有支援欄位的屬性 內的設定 set 存取子來進行設計,不過,由於 Age 這個屬性是在 Person 類別內,是無法知道與直接更新這個元件內的欄位 Field 或者 屬性 Property。
在這篇文章中,將會使用最常用的設計技術,也就是 事件 Event 來解決此一問題,也就是說,要透過 DOM 的事件來通知這個元件內的某個委派方法,告知所關注的物件已經有變動了,可以開始執行所綁定的委派方法。
  • 滑鼠右擊專案中的 [Pages] 資料夾節點
  • 點選 [加入] > [新增項目]
  • 現在 [新增項目] 對話窗將會出現
  • 在該對話窗最左邊,點選 [Visual C#]
  • 在該對話窗的中間,找到並點選 [Razor 元件] 選項
  • 在下方 [名稱] 欄位中,輸入 AgePropertyChanged
  • 點選右下方的 [新增] 按鈕
  • 完成新增這個元件檔案
  • 使用底下 Razor 元件標記與程式碼,替換該檔案內的原有內容
@page "/AgePropertyChanged"
@using System.ComponentModel.DataAnnotations

<h1>在 Blazor 使用 DOM 事件,設計屬性變更的需求</h1>
<h2>AgePropertyChanged</h2>
<div class="form-group">
    <label for="FirstName">名</label>
    <input id="FirstName" class="form-control" @bind="MyPerson.FirstName" />
</div>
<div class="form-group">
    <label for="LastName">姓</label>
    <input id="LastName" class="form-control" @bind="MyPerson.LastName" />
</div>
<div class="form-group">
    <label for="Age">年紀</label>

    <input type="number" id="Age" class="form-control"
           value="@MyPerson.Age"
           @oninput="@(x=>OnAge(x))" />
</div>

<button type="submit" class="btn btn-primary" disabled="@IsDisabled">Submit</button>

<div class="text-danger">
    @MyPerson.Age
</div>
<div class="text-danger">
    @AgeRange
</div>

@code{
    void OnAge(ChangeEventArgs e)
    {
        try
        {
            MyPerson.Age = Convert.ToInt32(e.Value);
        }
        catch { }
        AgeChanged();
    }

    class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Age { get; set; }
    }

    Person MyPerson = new Person();
    bool IsDisabled = true;
    string AgeRange = "";

    void AgeChanged()
    {
        if (MyPerson.Age < 13)
        {
            AgeRange = "你是小朋友";
            IsDisabled = true;
        }
        else if (MyPerson.Age < 20)
        {
            AgeRange = "你是年青人";
            IsDisabled = false;
        }
        else if (MyPerson.Age < 28)
        {
            AgeRange = "你是青年人";
            IsDisabled = false;
        }
        else
        {
            AgeRange = "你是成年人";
            IsDisabled = false;
       }
        StateHasChanged();
    }
}
首先,先來設計一個方法,用來根據當前的年紀,根據所指定的規格,設定適當的文字,這裡將會儲存到新加入的 AgeRange 欄位變數內,這裡將會設計到 AgeChanged() 方法內;而且,這個 AgeRange 變數,將會透過單向資料綁定 one-way data binding 的方式,使用底下宣告來顯示在螢幕上
<div class="text-danger">
    @AgeRange
</div>
另外,在 AgeChanged() 方法內,也會修正 IsDisabled 變數的數值內容,也就會間接影響到當時的按鈕是否可以使用,這裡透過了 disabled="@IsDisabled" 宣告方式,透過單向資料綁定來做到。
在這裡的原始碼中,將會發現到對於年紀的 HTML 標記宣告,變成了 <input type="number" id="Age" class="form-control" value="@MyPerson.Age" @oninput="@(x=>OnAge(x))" /> 這樣,原先使用 @bind="MyPerson.Age" 的雙向資料綁定宣告,修改成為了 value="@MyPerson.Age" 單向的資料綁定。

問題探討

若對於上述的說明不是很了解的,可以請讀者對於上述的說明進行研究之後,將你的看法留言在本部落格文章的留言處
由於現在變更成為了單向資料綁定,所以,就宣告了 @oninput="@(x=>OnAge(x))" /> oninput 指示詞 (directive)來做到綁定網頁端的 DOM 的事件 GlobalEventHandlers.oninput,也就是說,當使用者有輸入任何內容的時候,將會觸發這個元件中內 C# 的 OnAge 事件委派方法。
從 [OnAge] 方法中,將會看到有宣告一個參數,其型別為 ChangeEventArgs,這裡將會透過這個參數,取得使用者最新輸入的內容,該內容可以透過 e.Value 來取得。並且將該內容轉型成為 int 型別,最後設定到 MyPerson.Age 屬性上。
由於 MyPerson.Age 屬性已經有異動了,所以,將會根據當前的 MyPerson.Age 屬性值來計算出適當要顯示的訊息,並且決定按鈕是否要啟用。
底下的螢幕截圖,將會是執行結果:

Blazor 資料綁定的屬性變更

Blazor 資料綁定的屬性變更
Blazor 資料綁定的屬性變更