練習 - 在 Blazor 應用程式中共享數據

已完成

既然您的應用程式已連線到資料庫,現在可以新增客戶設定和訂購披薩的能力。

Blazing Pizza 希望您建置客戶變更其特殊披薩大小的能力。 您需要儲存訂單,而且您想要將應用程式狀態儲存在容器服務中。

在此練習中,您會將數據傳遞至新的訂單配置元件,並瞭解如何將應用程式的狀態儲存在 OrderState 範疇服務中。

新增訂單組態對話框

  1. 如果應用程式仍在執行中,請停止該應用程式。

  2. 在 Visual Studio Code 中,以滑鼠右鍵按兩下 [共享資料夾 ],然後選取 [ 新增檔案]。

  3. 輸入 ConfigurePizzaDialog.razor 作為檔名。

  4. 針對新排序元件的UI輸入此程式代碼:

    @inject HttpClient HttpClient
    
    <div class="dialog-container">
        <div class="dialog">
            <div class="dialog-title">
                <h2>@Pizza.Special.Name</h2>
                @Pizza.Special.Description
            </div>
            <form class="dialog-body">
                <div>
                    <label>Size:</label>
                    <input type="range" min="@Pizza.MinimumSize" max="@Pizza.MaximumSize" step="1" />
                    <span class="size-label">
                        @(Pizza.Size)" (£@(Pizza.GetFormattedTotalPrice()))
                    </span>
                </div>
            </form>
    
            <div class="dialog-buttons">
                <button class="btn btn-secondary mr-auto" >Cancel</button>
                <span class="mr-center">
                    Price: <span class="price">@(Pizza.GetFormattedTotalPrice())</span>
                </span>
                <button class="btn btn-success ml-auto" >Order ></button>
            </div>
        </div>
    </div>
    

    此元件是顯示所選特殊披薩的對話框,可讓客戶選取披薩大小。

    元件需要來自索引頁面元件的特製披薩,才能存取披薩的會員值。

  5. 新增 Blazor @code 區塊,以允許將參數傳遞至元件:

    @code {
        [Parameter] public Pizza Pizza { get; set; }
    }
    

訂購披薩

當客戶選取披薩時,對話框應該允許他們變更披薩的大小。 讓我們增強 index.razor 控件以新增此互動功能。

  1. 在檔案總管中,展開 [頁面],然後選取 [Index.razor]。

  2. @code 變數底下的 List<PizzaSpecial> 區塊中新增此程式碼:

    Pizza configuringPizza;
    bool showingConfigureDialog;
    
  3. OnInitializedAsync() 方法中新增此程式碼以建立披薩:

    void ShowConfigurePizzaDialog(PizzaSpecial special)
    {
        configuringPizza = new Pizza()
        {
            Special = special,
            SpecialId = special.Id,
            Size = Pizza.DefaultSize
        };
    
        showingConfigureDialog = true;
    }
    
  4. 藉由允許客戶選取披薩的 ShowConfigurePizzaDialog 標記來讓網頁呼叫伺服器端 <li> 方法。 將該 <li> 行取代為該程式碼:

    <li @onclick="@(() => ShowConfigurePizzaDialog(special))" style="background-image: url('@special.ImageUrl')">
    

    當客戶選擇披薩時,伺服器會 ShowConfigurePizzaDialog 執行 方法,以使用特殊的披薩數據建立披薩,並將變數設定 showingConfigureDialogtrue

  5. 頁面需要顯示新 ConfigurePizzaDialog 元件的方法。 在區塊上方 @code 新增此程式碼:

    @if (showingConfigureDialog)
    {
        <ConfigurePizzaDialog Pizza="configuringPizza" />
    }
    

    整個 index.razor 檔案現在看起來應該像下列範例:

    @page "/"
    @inject HttpClient HttpClient
    @inject NavigationManager NavigationManager
    
    <div class="main">
        <h1>Blazing Pizzas</h1>
        <ul class="pizza-cards">
        @if (specials != null)
        {
            @foreach (var special in specials)
            {
              <li @onclick="@(() => ShowConfigurePizzaDialog(special))" style="background-image: url('@special.ImageUrl')">
                <div class="pizza-info">
                <span class="title">@special.Name</span>
                @special.Description
                <span class="price">@special.GetFormattedBasePrice()</span>
                </div>
              </li>
            }
        }
        </ul>
    </div>
    
    @if (showingConfigureDialog)
    {
        <ConfigurePizzaDialog Pizza="configuringPizza" />
    }
    
    @code {
        List<PizzaSpecial> specials = new();
        Pizza configuringPizza;
        bool showingConfigureDialog;
    
        protected override async Task OnInitializedAsync()
        {
            specials = await HttpClient.GetFromJsonAsync<List<PizzaSpecial>>(NavigationManager.BaseUri + "specials");
        }
    
        void ShowConfigurePizzaDialog(PizzaSpecial special)
        {
            configuringPizza = new Pizza()
            {
                Special = special,
                SpecialId = special.Id,
                Size = Pizza.DefaultSize
            };
    
            showingConfigureDialog = true;
        }
    }
    
  6. 選取 F5 或選取 [ 執行]。 然後選取 [開始偵錯]。

  7. 選取披薩並監看新的對話框。

    顯示披薩訂購對話框的螢幕快照。

處理訂單狀態

目前,應用程式會顯示設定對話框,但不允許您取消或繼續訂購披薩。 若要管理訂單的狀態,您可以新增訂單狀態容器服務。

  1. 如果應用程式仍在執行中,請停止該應用程式。

  2. BlazingPizza 資料夾中建立新的資料夾。 將其命名 為 Services

  3. Services 資料夾中建立新的檔案。 將它命名 為OrderState.cs

  4. 輸入 類別的這個程式代碼:

    namespace BlazingPizza.Services;
    
    public class OrderState
    {
        public bool ShowingConfigureDialog { get; private set; }
        public Pizza ConfiguringPizza { get; private set; }
        public Order Order { get; private set; } = new Order();
    
        public void ShowConfigurePizzaDialog(PizzaSpecial special)
        {
            ConfiguringPizza = new Pizza()
            {
                Special = special,
                SpecialId = special.Id,
                Size = Pizza.DefaultSize,
                Toppings = new List<PizzaTopping>(),
            };
    
            ShowingConfigureDialog = true;
        }
    
        public void CancelConfigurePizzaDialog()
        {
            ConfiguringPizza = null;
    
            ShowingConfigureDialog = false;
        }
    
        public void ConfirmConfigurePizzaDialog()
        {
            Order.Pizzas.Add(ConfiguringPizza);
            ConfiguringPizza = null;
    
            ShowingConfigureDialog = false;
        }
    }
    

    您注意到 index.razor 元件中目前有程式碼,我們可以將其移至新類別中。 下一個步驟是在應用程式中提供這項服務。

  5. 在檔案總管中,選取 [Program.cs]。

  6. 在檔案中那些以 builder.Services. 開始的行中,加入這一行:

    builder.Services.AddScoped<OrderState>();
    

    在上一個練習中,我們在這裡新增了資料庫內容。 此程式碼加入了新的 OrderState 服務。 有了此程式代碼,我們現在可以在 index.razor 元件中使用它。

  7. 將下列 using 指示詞新增至檔案頂端。 這個指令會解析對 OrderState 類別的任何參考。

    using BlazingPizza.Services;
    
  8. 在檔案總管中,展開 [頁面],然後選取 [Index.razor]。

  9. 在檔案頂端的 底下 @inject NavigationManager NavigationManager,新增下列程序代碼:

    @using BlazingPizza.Services
    @inject OrderState OrderState
    
  10. configuringPizza 區塊中移除 showingConfigureDialogShowConfigurePizzaDialog()@code。 目前看起來應該如下所示:

    @code {
        List<PizzaSpecial> specials = new List<PizzaSpecial>();
    
        protected override async Task OnInitializedAsync()
        {
            specials = await HttpClient.GetFromJsonAsync<List<PizzaSpecial>>(NavigationManager.BaseUri + "specials");
        }
    }
    

    在程式碼引用您刪除的元素時,會出現錯誤。

  11. 將呼叫變更為 ShowConfigurePizzaDialog(special)),以使用 OrderState 版本:

    <li @onclick="@(() => OrderState.ShowConfigurePizzaDialog(special))" style="background-image: url('@special.ImageUrl')">
    
  12. 將參考值變更為 showingConfigureDialog 布林值:

    @if (OrderState.ShowingConfigureDialog)
    
  13. 使用 configuringPizza變更 參數:

    <ConfigurePizzaDialog Pizza="OrderState.ConfiguringPizza" />
    
  14. 選取 F5 或選取 [ 執行]。 然後選取 [開始偵錯]。

    如果一切正確,您不應該看到任何差異。 對話框將保持和以前一樣的顯示方式。

取消並下訂披薩訂單

您可能會注意到 OrderState 類別中有兩種方法尚未使用。 CancelConfigurePizzaDialogConfirmConfigurePizzaDialog 方法會關閉對話方塊,並在客戶確認訂單後,將披薩新增至 Order 物件。 讓我們將這些方法連線到組態對話框按鈕。

  1. 如果應用程式仍在執行中,請停止該應用程式。

  2. 在檔案總管中,展開 [共享]。 然後選取 [ConfigurePizzaDialog.razor]。

  3. 在區塊中 @code ,新增兩個新參數:

    @code {
       [Parameter] public Pizza Pizza { get; set; }
       [Parameter] public EventCallback OnCancel { get; set; }
       [Parameter] public EventCallback OnConfirm { get; set; }
    }
    `` `
    
    
  4. 按鈕現在可以新增 @onclick 指令。 將對話框按鈕的目前程式代碼變更為此標記:

    <div class="dialog-buttons">
        <button class="btn btn-secondary mr-auto" @onclick="OnCancel">Cancel</button>
        <span class="mr-center">
            Price: <span class="price">@(Pizza.GetFormattedTotalPrice())</span>
        </span>
        <button class="btn btn-success ml-auto" @onclick="OnConfirm">Order ></button>
    </div>
    
  5. 最後一個步驟是傳遞 OrderState 取消和確認訂單的方法。 在檔案總管中,展開 [頁面]。 然後選取 Index.razor

  6. 呼叫元件 ConfigurePizzaDialog 的程式代碼變更:

    <ConfigurePizzaDialog
        Pizza="OrderState.ConfiguringPizza"
        OnCancel="OrderState.CancelConfigurePizzaDialog"
        OnConfirm="OrderState.ConfirmConfigurePizzaDialog" />
    
  7. 選取 F5 或選取 [ 執行]。 然後選取 [開始偵錯]。

應用程式現在應該可讓客戶取消或新增已設定的披薩至訂單。 我們無法在披薩大小變更時顯示目前訂單或更新價格。 我們將在下一個練習中新增這些功能。