Blazor中的数据绑定:如何将值传播到组件之外? [英] Data binding in Blazor: How to propagate values out of a component?

查看:142
本文介绍了Blazor中的数据绑定:如何将值传播到组件之外?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个相当简单的组件,看起来像这样:

I have a fairly simple component, which looks like this:

<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; }
}

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

I now add this to a page like this:

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

@functions {
    private string _value;
}

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

When I enter text in the input field, it is correctly updated at You entered here: but not propagated to *You entered in MVVMTest":

我该怎么做才能使其正确传播?

What do I have to do to get this correctly propagated?

我可以考虑将Action<string>挂钩为第二个[Parameter],当文本更改时,它会在组件内部触发,但这似乎是一种骇人听闻的回旋方式.是必须完成的,还是有更好的方法?

I could think of hooking up an Action<string> as a second [Parameter] which I fire inside the component when the text is changed, but it seems like a hackish and roundabout way. Is it how it has to be done, or is there a better way?

Issac的答案无效,因为它偶然发现了@bind-value:oninput="@((e) => ValueChanged.Invoke(e.Value))"Cannot convert lambda expression to type 'object' because it is not a delegate type.

The answer from Issac does not work because it stumbles over @bind-value:oninput="@((e) => ValueChanged.Invoke(e.Value))" with Cannot convert lambda expression to type 'object' because it is not a delegate type.

我必须以这种回旋的方式来做:

I had to do it in this roundabout way:

<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 Service的调用,因此我必须进行详尽的检测,确定谁更改了哪些内容以避免无限循环.

Not pretty, but it works. My "real" component is more complicated as a changed value triggers calls to the underlying ASP.net Core Service so I have to do elaborate detection who changes what to avoid infinite loops.

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

It would surely be better if Blazor supported XAML/WPF-like MVVM though...

我回到了Issac的解决方案,并进行了额外的演员安排,使它可以正常工作:

I came back to Issac's solution and with an extra cast, I got it working:

<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中的一个已知问题.我上周已经绊倒了,我发布了变通方法 .

This is already a known issue in Blazor. I tripped over this last week already, and I posted the workaround in the VS developer forum as well.

推荐答案

您需要添加EventCallback参数来做到这一点:

You need to add an EventCallback parameter to do that:

@code {

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

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

阅读数据绑定/组件参数

这篇关于Blazor中的数据绑定:如何将值传播到组件之外?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆