Select 组件比较难做,因为它有确定类型为string 的显示值,还有不确定类型的返回值。首先需要一个专门的类作为其下拉列的返回值和显示值,其次因返回值的不确定性,需要进行转换来确定。第三,如果本身有初始值,Select 不像 CheckBox 那样简单的初始化。
首先是专门的类:
[Serializable]
public class SelectItem
{
private string? text;
public object Value { get; set; } = default!;
public string Text
{
get
{
if (text == null) { return Value.ToString() ?? throw new NullReferenceException("返回值不能为空!"); } //如果Text值未设置,显示Value值。
return text;
}
set { text = value ?? throw new NullReferenceException("显示值不能为空!"); }
}
public int Id
{
set => Value = value;
}
public string ID //如果是string的Id,改为大写D
{
set => Value = value;
}
public string Name
{
set => Text = value;
}
public string DisplayName
{
set => Text = value;
}
public IList<SelectItem>? ChildItems { get; set; }
}
其次就是Select组件:
@typeparam TValue
<div class="d-md-flex">
<label class="control-label w-auto mt-2"><b>@Lable</b></label>
<div style="width:@SelectWidth">
<select value="@selectedValue" class="form-select" @onchange="SelectChanged" disabled="@Disabled">
@if (HasAll)
{
<option value="@string.Empty">全部</option>
}
@foreach (var item in Source)
{
<option value="@item.Value">@item.Text</option>
}
</select>
</div>
</div>
@code {
[Parameter]
public required string Lable { get; set; }
[Parameter]
public required TValue Value { get; set; }
[Parameter]
public string SelectWidth { get; set; } = "200";
[Parameter]
public required IEnumerable<SelectItem> Source { get; set; }
[Parameter]
public EventCallback<TValue> ValueChanged { get; set; }
[Parameter]
public bool Disabled { get; set; }
[Parameter]
public bool HasAll { get; set; }
private object? selectedValue;
private async void SelectChanged(ChangeEventArgs e)
{
if (e.Value != null)
{
var value = (TValue)e.Value;
await ValueChanged.InvokeAsync(value);
}
}
protected override void OnParametersSet()
{
base.OnParametersSet();
selectedValue = (object)Value;
SelectWidth += "px";
Lable += ":";
}
}
使用:
<Select TValue="string" HasAll="true" Source="SelectItems" @bind-Value="Message1" Lable="选择测试:"></Select>
<div><p>选项值:@Message1</p></div><Select TValue="string" HasAll="true" Source="SelectItems" @bind-Value="Message2" Lable="选择测试:"></Select>
<div><p>选项值:@Message2</p></div>
@code {
private string Message1 = "";//无初始值
private string Message2 = "选项值5";//有初始值
private IEnumerable<SelectItem> SelectItems = new List<SelectItem>
{
new SelectItem{Value="选项值1",Text = "选项1"},
new SelectItem{Value="选项值2",Text = "选项2"},
new SelectItem{Value="选项值3",Text = "选项3"},
new SelectItem{Value="选项值4",Text = "选项4"},
new SelectItem{Value="选项值5",Text = "选项5"},
new SelectItem{Value="选项值6",Text = "选项6"}
};
效果: