Blazor中的数据绑定:如何将值传播到组件之外? [英] Data binding in Blazor: How to propagate values out of a component?
问题描述
我有一个相当简单的组件,看起来像这样:
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屋!