Blazor 中的数据绑定:如何将值传播到组件之外?

问题描述 投票:0回答:1

我有一个相当简单的组件,如下所示:

<form>
    <div class="form-group">
        <label for="sampleText">Sample Text</label>
        <input type="text"
               class="form-control"
               id="sampleText"
               aria-describedby="sampleTextHelp"
               placeholder="Enter a text"
               @bind="@Value" />
        <small id="sampleTextHelp" class="form-text text-muted">Enter a text to test the databinding</small>
    </div>
</form>
<p>You entered here: @Value</p>

@code {

    [Parameter]
    public string Value { get; set; }
}

我现在将其添加到这样的页面中:

<MVVMTest Value="@_value" />
<p>
    You entered in MVVMTest:
    @_value
</p>

@functions {
    private string _value;
}

当我在输入字段中输入文本时,它会在 您在此处输入: 正确更新,但不会传播到 *您在 MVVMTest 中输入”:

MVVM not working

我需要做什么才能正确传播它?

我可以考虑将一个

Action<string>
作为第二个
[Parameter]
,当文本更改时我会在组件内触发它,但这似乎是一种黑客和迂回的方式。是必须这样做吗,还是有更好的方法?

后续1

Issac 的答案不起作用,因为它用

@bind-value:oninput="@((e) => ValueChanged.Invoke(e.Value))"
绊倒了
Cannot convert lambda expression to type 'object' because it is not a delegate type

我不得不用这种迂回的方式来做:

<form>
    <div class="form-group">
        <label for="sampleText">Sample Text</label>
        <input type="text"
               class="form-control"
               id="sampleText"
               aria-describedby="sampleTextHelp"
               placeholder="Enter a text"
               @bind="@Value" />
        <small id="sampleTextHelp" class="form-text text-muted">Enter a text to test the databinding</small>
    </div>
</form>
<p>You entered here: @Value</p>

@code {

    private string _value;

    [Parameter]
    public string Value {
        get => _value;
        set {
            if(Equals(value, _value)) {
                return;
            }
            _value = value;
            OnValueChanged.InvokeAsync(value).GetAwaiter().GetResult();
        }
    }

    [Parameter]
    public EventCallback<string> OnValueChanged { get; set; }
}

并像这样使用它:

@inject HttpClient http
@page "/test"
<div class="top-row px-4">
    Test Page
</div>

<div class="content px-4">
    <MVVMTest Value="@_value" OnValueChanged="@(v => _value = v)" />
    <p>
        You entered in MVVMTest:
        @_value
    </p>
</div>

@functions {
    private string _value;
}

不漂亮,但有效。我的“真实”组件更加复杂,因为更改的值会触发对底层 ASP.net Core 服务的调用,因此我必须仔细检测谁更改了内容以避免无限循环。

如果 Blazor 支持类似 XAML/WPF 的 MVVM,那肯定会更好......

后续2

我回到 Issac 的解决方案,并通过额外的演员,我让它工作了:

<form>
    <div class="form-group">
        <label for="sampleText">Sample Text</label>
        <input type="text"
               class="form-control"
               id="sampleText"
               aria-describedby="sampleTextHelp"
               placeholder="Enter a text"
               value="@Value"
               oninput="@((Func<ChangeEventArgs, Task>)(async e => await OnValueChanged.InvokeAsync(e.Value as string)))" />
        <small id="sampleTextHelp" class="form-text text-muted">Enter a text to test the databinding</small>
    </div>
</form>
<p>You entered here: @Value</p>

@code {

    private string _value;

    [Parameter]
    public string Value { get; set; }

    [Parameter]
    public EventCallback<string> OnValueChanged { get; set; }
}

用途:

<MVVMTest Value="@_value" OnValueChanged="@(v => _value = v)" />
<p>
    You entered in MVVMTest:
    @_value
</p>

@functions {
    private string _value;
}

这已经是 Blazor 中的一个已知问题。上周我已经被这个问题绊倒了,我也在 VS 开发者论坛发布了解决方法。

c# mvvm data-binding blazor
1个回答
4
投票
您需要添加一个 EventCallback 参数来执行此操作:

@code { [Parameter] public string Value { get; set; } [Parameter] public EventCallback<string> ValueChanged { get; set; } }
阅读

与组件参数绑定部分。

© www.soinside.com 2019 - 2024. All rights reserved.