Blazor:绑定到 MultiSelectList(最好带有复选框)

DrG*_*iff 8 data-binding multi-select blazor blazor-server-side

尝试使用 Blazor(服务器,如果这有什么不同的话),我很难绑定到 MultiSelectList 以工作......

一点背景:我正在处理 EF Core 并且有一个多对多的关系,比如说人和汽车之间的关系。我目前正在加载一个显示现有详细信息的页面,并允许用户更新此页面。

所以在我的服务中,我从数据库加载了我的 Person 实体,这包括他们当前拥有的所有汽车的详细信息。我还加载了所有可用汽车的列表。然后,我的 Service 方法创建一个 MultiSelectList 并将其添加到我的 ViewModel(将返回到 Razor 页面):

服务方式

vm.CarSelector = new MultiSelectList(
     allCars,
     nameof(Car.CarId), 
     nameof(Car.Name), 
     person.OwnedCars.Select(oc => oc.CarId));
Run Code Online (Sandbox Code Playgroud)

这是虚构的代码,但我希望你能得到图片。在调试这个时(在 Service 方法中),我可以看到这个 MultiSelectList 为每辆车都有一个条目,已经选择的条目显示为 Selected。伟大的!

Blazor 剃刀页

所以,这就是我解脱的地方......我不知道如何将 Razor 控件的双向数据绑定到这个对象。

  • 我正在尝试使用 <InputSelect />,但这可能不是最好的控件。
  • 理想情况下(实际上,这更像是“必须拥有”),每个选项都应该有 CheckBox。
  • 我想知道使用 MultiSelectList 是否真的能给我带来任何好处

Eri*_*and 6

blazor 中的复选框略有不同。通常,您会在输入元素上使用 bind-value 属性,如下所示,但是,不建议这样做,因为您将只能通过代码更改布尔值来读取值而不能更新 UI:

    <input type="checkbox" @bind-value="@item.Selected"/>
Run Code Online (Sandbox Code Playgroud)

相反,对复选框使用 @bind 语法,它更健壮,并且可以双向工作(更改代码中的绑定布尔值并与 UI 上的复选框交互)。请参阅以下语法:

    <input type="checkbox" @bind="@item.Selected"/>
Run Code Online (Sandbox Code Playgroud)

bind 属性会自动将你的布尔值绑定到 html 元素的“checked”属性。

还要确保您绑定到“Selected”属性而不是“Value”属性。

使用内置绑定将避免需要像您在答案中所做的那样手动设置事件。您还可以摆脱 if/else 块并将您的代码合并到单个代码流中,因为您现在绑定到布尔值而不是手动设置检查属性。如果您仍然需要利用一个事件来触发某些进程(可能在选中一个框时隐藏部分 UI),我建议使用 onclick 事件并手动传递每行的多选项。这是最终的代码:

@foreach(var item in list)
{
    <input type="checkbox" @bind="item.Selected" @onclick="(()=>handleClick(item))" />
}
@foreach(var item in list.Where(x=>x.Selected))
{
    <p> Item @item.Text is Selected</p>
}

@code {
    MultiSelectList list = new MultiSelectList(new List<Car> { new Car { Year = 2019, Make = "Honda", Model = "Accord" }, new Car { Make = "Honda", Model = "Civic", Year = 2019 } });

    private void handleClick(SelectListItem item)
    {        
        //Do something crazy
    }

}
Run Code Online (Sandbox Code Playgroud)


DrG*_*iff 5

我让它与一个以 MultiSelectList 作为参数的组件一起工作。可能有更优雅的方法来实现这一点(如果您知道更好的方法,请进行更新)。

@using Microsoft.AspNetCore.Components
@using Microsoft.AspNetCore.Mvc.Rendering

<div class="multiselect">
    <div id="checkboxes">
        @foreach (var item in this.Items)
        {
            <div>
                <label for="@item.Value">
                    @if (item.Selected)
                    {
                        <input type="checkbox" id="@item.Value" checked="checked" @onchange="@((e) => CheckboxChanged(e, item.Value))" />
                    }
                    else
                    {
                        <input type="checkbox" id="@item.Value" @onchange="@((e) => CheckboxChanged(e, item.Value))" />
                    }
                    @item.Text
                </label>
            </div>
        }
    </div>
</div>

@code
{
    [Parameter]
    public MultiSelectList Items { get; set; } = null!;

    private void CheckboxChanged(ChangeEventArgs e, string key)
    {
        var i = this.Items.FirstOrDefault(i => i.Value == key);
        if (i != null)
        {
            i.Selected = (bool)e.Value;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)