【发布时间】:2021-03-19 04:38:21
【问题描述】:
注意为了更清楚我在做什么,我添加了sample project to github。这显示了
FormRowText组件的使用,它工作正常,而FormRowDropdownEnum组件,它不起作用。如果有人能够下载这个项目并看看我做错了什么,那就太好了。
我正在尝试编写一系列可重用的 Blazor 组件来布置表单控件。其中大多数都在工作(例如<input>),但其中一个给我带来了问题。想法是将enum的类型作为参数传递,组件将根据enum的值创建<select>。
我做了一个通用组件如下(.razor first)...
@typeparam T
<div class="form-group row">
<label for="@PropertyName" class="col-lg-2 col-form-label">@(Caption ?? PropertyName)</label>
<div class="col-lg-10 input-group">
<div class="input-group-prepend">
<span class="input-group-text">
<i class="far fa-@Icon"></i>
</span>
</div>
<select class="form-control" name="@PropertyName" id="@PropertyName" @onchange="@OnChanged">
@foreach (T v in Enum.GetValues(typeof(T)).Cast<T>()) {
if ((int)Enum.Parse(typeof(T), v.ToString()) == Value) {
<option value="@Convert.ToInt32(v)" selected>@Enum.GetName(typeof(T), v)</option>
} else {
<option value="@Convert.ToInt32(v)">@Enum.GetName(typeof(T), v)</option>
}
}
</select>
</div>
</div>
后面的代码是这样的……
public partial class FormRowDropdownEnum<T> where T : Enum, IConvertible {
[Parameter]
public int Value { get; set; }
[Parameter]
public EventCallback<int> ValueChanged { get; set; }
[Parameter]
public string PropertyName { get; set; }
[Parameter]
public string Caption { get; set; }
[Parameter]
public string Icon { get; set; }
private async Task OnChanged(ChangeEventArgs cea) {
int val = (int)Enum.Parse(typeof(T), cea.Value?.ToString() ?? "0");
await ValueChanged.InvokeAsync(val);
}
}
它的用法如下(假设_customer是一个模型,它有一个Frequency参数,它的类型是Frequency(一个enum)...
<FormRowDropdownEnum PropertyName="@nameof(Customer.Frequency)"
T="Frequency" @bind-Value="(int)_customer.Frequency" Icon="wave-sine" />
这会正确显示<select>,并根据模型的Frequency 参数设置适当的<option>。
当<select>中的选择发生变化时,调用OnChanged方法,并将正确的值作为事件回调的参数。但是,包含此组件的 Blazor 页面(即上面显示的具有<FormRowDropdownEnum> 标记的页面)永远不会看到新值,并且那里的模型没有更新。我在模型的 setter 上放了一个断点,它从未被命中。
正如我所说,我有用于其他输入类型的类似组件,并且它们工作正常,所以我不确定我在这里做错了什么。
有人可以帮忙吗?谢谢
更新根据enet的回复,我尝试在后面的代码中添加一个私有变量,并在输入值更改时对其进行修改...
private int _value;
protected override void OnParametersSet() =>
_value = Value;
private async Task OnChanged(ChangeEventArgs cea) {
int val = (int)Enum.Parse(typeof(T), cea.Value?.ToString() ?? "0");
_value = val;
await ValueChanged.InvokeAsync(val);
}
我将 Razor 标记更改为使用 _value 而不是 Value,如下所示...
if ((int)Enum.Parse(typeof(T), v.ToString()) == _value) {
但是,这样做的结果是,当我在下拉菜单中更改选择时,它立即恢复为之前的值,并且父页面再也没有看到新的值。
【问题讨论】:
标签: blazor