c# - Blazor 中的数据绑定:如何将值传播出组件?
问题描述
我有一个相当简单的组件,如下所示:
<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]
是必须这样做,还是有更好的方法?
跟进 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 核心服务的调用,因此我必须仔细检测谁更改了哪些内容以避免无限循环。
如果 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 开发者论坛上发布了解决方法。
解决方案
您需要添加一个 EventCallback 参数来执行此操作:
@code {
[Parameter]
public string Value { get; set; }
[Parameter]
public EventCallback<string> ValueChanged { get; set; }
}
阅读数据绑定/组件参数部分
推荐阅读
- linkedin - 使用 LinkedIn V2 API 使用视频资产创建 UGC 帖子
- python - 如何总结不同的groupby组合?
- presto - 无法在 Presto 上使用 PostgresSQL 访问 LocalHost
- reactjs - 从 GraphQL Schema 自动生成数据导航
- node.js - Lambda 函数不能与 Alexa 技能一起使用?
- jquery - 无法在顶部使用固定菜单栏制作修复后滚动 div
- java - 以编程方式更改应用程序资源语言后,SlidingTabLayout 的选项卡语言不会更改
- javascript - 反应 keyDown 事件有时在 KeyUp 上触发
- python - Selenium:获取滚动页面的 HTML
- jquery - Jquery UI Sortable 存在