簡體   English   中英

Blazor中class的雙向組件參數綁定?

[英]Two-Way Component Parameter Binding on a class in Blazor?

我有一個 class MealsQueryInputs ,我想將其用作具有雙向綁定功能的組件參數。

我能找到的所有演示和示例代碼都使用內置原始類型,而不是 class。我可以讓MS 演示工作,但我無法綁定到 class 工作。 甚至可以這樣做嗎?

我的組件FilterSortOptions.razor

using WhatIsForDinner.Shared.Models

<MudCheckBox Checked="@QueryInputs.Favorite" 
             Color="Color.Inherit" 
             CheckedIcon="@Icons.Material.Filled.Favorite" 
             UncheckedIcon="@Icons.Material.Filled.FavoriteBorder"
             T="bool"/>
<MudRating SelectedValue="@QueryInputs.Rating"/>
<MudButton OnClick="@(async () => await OnPropertyChanged())">Apply</MudButton>

@code {
    [Parameter]
    public MealsQueryInputs QueryInputs { get; set; }

    [Parameter]
    public EventCallback<MealsQueryInputs> QueryInputsChanged { get; set; }

    private async Task OnPropertyChanged()
    {
        await QueryInputsChanged.InvokeAsync(QueryInputs);
    }
}

正如 MrC 所說,您應該避免直接綁定到作為參數提供的數據。

這是一個簡單的工作示例(不是 MudBlazor)來展示這個概念

https://blazorrepl.telerik.com/QQEnQjaO54LY3MYK35

您綁定到局部變量/屬性,並盡量不要直接修改傳入的數據。

我的組件


<h1>MyComponent</h1>

<label for="choice">Choose</label>
<input id="choice" type="checkbox" @bind-value=localValue  />

@code
{
    bool localValue
    {
        get => Data.SomeChoice;
        set {
            if (value != localValue)
            {
                localData = Data with { SomeChoice = value };
                InvokeAsync(ValueChanged);
            }
        }
    }
    ComplexObject localData;
    [Parameter] public ComplexObject Data { get; set; }
    [Parameter] public EventCallback<ComplexObject> DataChanged { get; set; }

    Task ValueChanged() => DataChanged.InvokeAsync(localData);
}

復雜對象

public record ComplexObject(bool SomeChoice, string SomeText);

主要的

@code
{
    ComplexObject data = new(false,"");
}

<MyComponent @bind-Data=data />

You have chosen @data.SomeChoice

以下是如何將 class 對象綁定到自定義 razor 組件

這是 FilterSortOptions 組件

<div>
    <label>Rating:</label>
    <input type="text" value=@QueryInputs.Rating @oninput=@(val=> {
           QueryInputs.Rating=val.Value.ToString();
           QueryInputsChanged.InvokeAsync(QueryInputs);
           }) />
</div>

<div>
    <label>Favourite:</label>
    <input type="checkbox" value=@QueryInputs.Rating @onchange=@(val=> {
           QueryInputs.Favourite=(bool)val.Value;
           QueryInputsChanged.InvokeAsync(QueryInputs);
           }) />
</div>

    @code {
    
        [Parameter]
        public MealsQueryInputs QueryInputs { get; set; }
    
        [Parameter]
        public EventCallback<MealsQueryInputs> QueryInputsChanged { get; set; }
    
    }

這里綁定的是model,為了簡單起見Rating是string類型

public class MealsQueryInputs
{
    public bool Favourite { get; set; } = false;
    public string Rating { get; set; } = "0";
}

這是razor頁面

<h3>Rating: @QueryInputs.Rating</h3>
<h3>Favourite: @QueryInputs.Favourite</h3>

<FilterSortOptions @bind-QueryInputs=@QueryInputs></FilterSortOptions>

@code {
    public MealsQueryInputs QueryInputs = new();
}

更新的答案

首先,如果您使用 object,那么您將傳遞對相同 object 的引用。因此,當您更新子組件中的 object 時,您將更新父組件正在使用的相同 object。 您不需要在回調中傳回 object,除非您創建它的新副本。

其次,您沒有將泥漿控件綁定到 object。

讓我們看看你的代碼:

<MudCheckBox Checked="@QueryInputs.Favorite" 
             Color="Color.Inherit" 
             CheckedIcon="@Icons.Material.Filled.Favorite" 
             UncheckedIcon="@Icons.Material.Filled.FavoriteBorder"
             T="bool"/>

Checked="@QueryInputs.Favorite"不會將控件綁定到字段。 它只是設置初始值。

我認為(我不使用 Mudblazor,它與標准的 Blazor 表單控件有點不同)你需要這樣做:

<MudCheckBox @bind-Checked="@QueryInputs.Favorite"></MudCheckBox>

MudRating也是如此。

    <MudRating @bind-SelectedValue="@QueryInputs.Rating" />

然后是按鈕:

<MudButton OnClick="@(async () => await OnPropertyChanged())">Apply</MudButton>

可以簡化成這樣。 您將異步方法包裝在異步方法中。

<MudButton OnClick="OnPropertyChanged">Apply</MudButton>
// or
<MudButton OnClick="() => OnPropertyChanged()">Apply</MudButton>

原始答案

這里有幾個問題:

  1. QueryInputs是一個Parameter ,因此永遠不應被組件內的代碼修改。 您最終會發現渲染器認為的值與實際值不匹配。

  2. 當父組件呈現時,它總是會導致重新呈現作為參數傳遞 class 的任何組件。 渲染器無法判斷 class 是否已被修改,因此它應用了笨拙的解決方案 - 在組件上調用SetParametersAsync

一種解決方案是使用視圖服務來保存數據和事件以通知更改。 一個版本的真相。 搜索“Blazor Notification Pattern”以獲取有關如何實現此功能的示例。 如果你找不到你想要的,我會發布一些代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM