我有一个相当简单的组件,如下所示:
<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 中输入”:
我需要做什么才能正确传播它?
我可以考虑将一个
Action<string>
作为第二个 [Parameter]
,当文本更改时我会在组件内触发它,但这似乎是一种黑客和迂回的方式。是必须这样做吗,还是有更好的方法?
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,那肯定会更好......
我回到 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 开发者论坛发布了解决方法。
@code {
[Parameter]
public string Value { get; set; }
[Parameter]
public EventCallback<string> ValueChanged { get; set; }
}
阅读与组件参数绑定部分。