Blazor: привязка к MultiSelectList (в идеале с флажком) - PullRequest
0 голосов
/ 10 октября 2019

Экспериментируя с Blazor (Сервер, если это что-то меняет), и у меня возникают трудности с привязкой к MultiSelectList для работы ....

Немного предыстории: я имею дело с EF Coreи иметь отношения «многие ко многим», скажем, между людьми и автомобилями. В настоящее время я загружаю страницу, которая показывает существующие детали, и позволяю пользователю обновить эту страницу.

Итак, в моем Сервисе я загружаю свою сущность Person из БД, и она включает в себя детали всехавтомобили, которыми они в настоящее время владеют. Я также загружаю список всех доступных автомобилей. Мой метод Service затем создает MultiSelectList и добавляет его в мою ViewModel (для возврата на страницу Razor):

Метод Service

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

Это фиктивный код, но я надеюсь, что вы получите картину. При отладке этого (в методе Service) я вижу, что этот MultiSelectList имеет запись для каждого автомобиля, а те, которые уже выбраны, отображаются как выбранные. Отлично!

Страница Blazor Razor

Итак, вот тут я и отклеился ... Я не могу понять, как работать с двусторонними данными. привязка элемента Razor к этому объекту.

  • Я пытаюсь использовать, но это, возможно, не лучший контроль для использования.
  • в идеале (на самом деле, это больше «обязательно иметь»), каждый параметр должен иметь CheckBox.
  • Мне интересно, действительно ли использование MultiSelectList мне что-нибудь да дает

Ответы [ 2 ]

1 голос
/ 12 октября 2019

Флажки немного отличаются в блазоре. Обычно вы используете атрибут bind-value для элемента ввода, как показано ниже, однако это не рекомендуется, поскольку вы сможете только читать значение и НЕ обновлять пользовательский интерфейс, изменяя логическое значение с помощью кода:

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

Вместо этого используйте синтаксис @bind для флажков, который намного более надежен и будет работать в обоих направлениях (изменение связанного логического значения из кода и взаимодействие с флажком в пользовательском интерфейсе). Смотрите синтаксис ниже:

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

Атрибут bind автоматически свяжет ваше логическое значение со свойством «checked» элемента html.

Также убедитесь, что вы привязываете к свойству Selected, а не к значению Value.

Использование встроенной привязки избавит от необходимости вручную настраивать события, как вы делали в своем ответе. Вы также можете избавиться от блока if / else и объединить свой код в единый поток кода, поскольку теперь вы привязываетесь к логическому значению, а не устанавливаете свойство selected вручную. Если вам все еще нужно подключиться к событию, чтобы запустить какой-то процесс (возможно, скрыть части пользовательского интерфейса при установке флажка), я бы предложил использовать событие 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
    }

}
0 голосов
/ 11 октября 2019

Я получил это для работы с компонентом, который принимает 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;
        }
    }
}
...