关于多选:Blazor:绑定到MultiSelectList(理想情况下带有复选框)

Blazor: binding to a MultiSelectList (ideally with a checkbox)

试用Blazor(服务器,如果有任何不同),我很难绑定到MultiSelectList来工作。

背景知识:我正在与EF Core打交道,并且在人与汽车之间建立了多对多关系。我当前正在加载一个显示现有详细信息的页面,并允许用户更新此页面。

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

服务方式

1
2
3
4
5
vm.CarSelector = new MultiSelectList(
     allCars,
     nameof(Car.CarId),
     nameof(Car.Name),
     person.OwnedCars.Select(oc => oc.CarId));

这是虚拟代码,但我希望您能理解。调试时(在Service方法中),我可以看到此MultiSelectList为每个汽车都有一个条目,并且已经选择的汽车显示为Selected。大!

剃刀剃刀页面

因此,这就是我要解决的问题...。我无法解决如何将Razor控件双向数据绑定到该对象。

  • 我正在尝试使用,但这可能不是最好的控件。
  • 理想情况下(实际上,更多的是"必须拥有"),每个选项都应具有CheckBox。
  • 我想知道使用MultiSelectList是否真的给我买了什么

我将其与使用MultiSelectList作为参数的组件一起使用。可能有更优雅的方法来实现此目的(如果您知道更好的方法,请进行更新)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@using Microsoft.AspNetCore.Components
@using Microsoft.AspNetCore.Mvc.Rendering


   
        @foreach (var item in this.Items)
        {
           
                <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>
           
        }
   


@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;
        }
    }
}


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

1
    <input type="checkbox" @bind-value="@item.Selected"/>

取而代之的是,对复选框使用@bind语法,该语法更加健壮,并且可以双向工作(从代码更改绑定的布尔值并与UI上的复选框进行交互)。请参见以下语法:

1
    <input type="checkbox" @bind="@item.Selected"/>

bind属性将自动将布尔值绑定到html元素的" checked"属性。

另外,请确保您绑定到" Selected"属性而不是" Value"属性。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@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
    }

}