Выберите Tag Helper в ASP.NET ядро MVC

мне нужна помощь с помощником select tag в ASP.NET ядро.

у меня есть список сотрудников, которых я пытаюсь привязать к помощнику select tag. Мои сотрудники в List<Employee> EmployeesList и выбранное значение перейдет в EmployeeId собственность. Моя модель выглядит так:

public class MyViewModel
{
   public int EmployeeId { get; set; }
   public string Comments { get; set; }
   public List<Employee> EmployeesList {get; set; }
}

мой класс employee выглядит так:

public class Employee
{
   public int Id { get; set; }
   public string FullName { get; set; }
}

мой вопрос в том, как сказать моему помощнику select tag использовать Id как значение при отображении FullName в выпадающем список?

<select asp-for="EmployeeId" asp-items="???" />

Я был бы признателен за помощь в этом. Спасибо.

5 ответов


использование помощников Select Tag для отображения элемента SELECT в вашем представлении

в вашем действии GET создайте объект вашей модели представления, загрузите EmployeeList свойство коллекции и отправьте его в представление.

public IActionResult Create()
{
    var vm = new MyViewModel();
    vm.EmployeesList = new List<Employee>
    {
        new Employee { Id = 1, FullName = "Shyju" },
        new Employee { Id = 2, FullName = "Bryan" }
    };
    return View(vm);
}

и в вашем представлении create создайте новый SelectList объект EmployeeList свойство и передать это как значение для asp-items собственность.

@model MyViewModel
<form asp-controller="Home" asp-action="Create">

    <select asp-for="EmployeeId" 
            asp-items="@(new SelectList(Model.EmployeesList,"Id","FullName"))">
        <option>Please select one</option>
    </select>

    <input type="submit"/>

</form>

и ваш метод действия HttpPost для принятия представленной формы данные.

[HttpPost]
public IActionResult Create(MyViewModel model)
{
   //  check model.EmployeeId 
   //  to do : Save and redirect
}

или

если ваша модель имеет вид List<SelectListItem> как свойство для ваших выпадающих элементов.

public class MyViewModel
{
    public int EmployeeId { get; set; }
    public string Comments { get; set; }
    public List<SelectListItem> Employees { set; get; }
}

и в вашем действии get,

public IActionResult Create()
{
    var vm = new MyViewModel();
    vm.Employees = new List<SelectListItem>
    {
        new SelectListItem {Text = "Shyju", Value = "1"},
        new SelectListItem {Text = "Sean", Value = "2"}
    };
    return View(vm);
}

и в представлении, вы можете напрямую использовать Employees свойство asp-items.

@model MyViewModel
<form asp-controller="Home" asp-action="Create">

    <label>Comments</label>
    <input type="text" asp-for="Comments"/>

    <label>Lucky Employee</label>
    <select asp-for="EmployeeId" asp-items="@Model.Employees" >
        <option>Please select one</option>
    </select>

    <input type="submit"/>

</form>

класс SelectListItem принадлежит Microsoft.AspNet.Mvc.Rendering пространство имен.

убедитесь, что вы используете явный закрывающий тег для элемента select. Если вы используете в самозакрывания подход таг, вспомогательный тег будет отображаться пустой выберите элемент!

ниже подход не работает

<select asp-for="EmployeeId" asp-items="@Model.Employees" />

но это сработает.

<select asp-for="EmployeeId" asp-items="@Model.Employees"></select>

получение данных из таблицы базы данных с помощью entity framework

в приведенных выше примерах используются жестко закодированные элементы для опций. Поэтому я подумал, что добавлю пример кода для получения данных с использованием Entity framework как много людей использовать это.

предположим, что ваш объект DbContext имеет свойство Employees типа DbSet<Employee> здесь Employee класс сущностей имеет Id и Name имущества

public class Employee
{
   public int Id { set; get; }
   public string Name { set; get; }
}

вы можете использовать запрос linq для получения сотрудников и использовать метод Select в выражении linq для создания списка SelectListItem предметы для каждого сотрудника.

public IActionResult Create()
{
    var vm = new MyViewModel();
    vm.Employees = context.Employees
                          .Select(a => new SelectListItem() {  
                              Value = a.Id.ToString(),
                              Text = a.Name
                          })
                          .ToList();
    return View(vm);
}

предполагая, что context - это объект контекста БД. Код представления такой же, как выше.

Использование SelectList

некоторые люди предпочитают использовать SelectList класс для хранения элементов, необходимых для отображения параметров.

public class MyViewModel
{
    public int EmployeeId { get; set; }
    public SelectList Employees { set; get; }
}

теперь в вашем действии GET вы можете использовать SelectList конструктор для заполнения Employees свойства модели представления. Убедитесь, что вы указываете dataValueField и dataTextField параметры.

public IActionResult Create()
{
    var vm = new MyViewModel();
    vm.Employees = new SelectList(GetEmployees(),"Id","FirstName");
    return View(vm);
}
public IEnumerable<Employee> GetEmployees()
{
    return new List<Employee>
    {
        new Employee { Id=1, FirstName="Shyju"},
        new Employee { Id=2, FirstName="Bryan"}
    };
}

вот я вызываю GetEmployees метод для получения списка объектов Employee, каждый с Id и FirstName property и я использую эти свойства как DataValueField и DataTextField на SelectList объект, который мы создали. Вы можете изменить жестко закодированный список на код, который считывает данные из таблицы базы данных.

код представления будет таким же.

<select asp-for="EmployeeId" asp-items="@Model.Employees" >
    <option>Please select one</option>
</select>

отображение элемента SELECT из списка строк.

иногда может потребоваться отобразить элемент select из списка строк. В этом случае, вы можете использовать SelectList конструктор, который принимает только IEnumerable<T>

var vm = new MyViewModel();
var items = new List<string> {"Monday", "Tuesday", "Wednesday"};
vm.Employees = new SelectList(items);
return View(vm);

код представления будет таким же.

настройка выбранных параметров

иногда вы можете установить один параметр в качестве параметра по умолчанию в элементе SELECT (например, на экране редактирования вы хотите загрузить ранее сохраненное значение параметра). Для этого вы можете просто установить EmployeeId значение свойства для значения параметра, который вы хотите выбрать.

public IActionResult Create()
{
    var vm = new MyViewModel();
    vm.Employees = new List<SelectListItem>
    {
        new SelectListItem {Text = "Shyju", Value = "11"},
        new SelectListItem {Text = "Tom", Value = "12"},
        new SelectListItem {Text = "Jerry", Value = "13"}
    };
    vm.EmployeeId = 12;  // Here you set the value
    return View(vm);
}

это позволит выбрать опция Tom в элементе select при отображении страницы.

Multi выберите выпадающее меню

если вы хотите отобразить раскрывающийся список multi select, вы можете просто изменить свойство модели представления, которое вы используете для asp-for атрибут в представлении к типу массива.

public class MyViewModel
{
    public int[] EmployeeIds { get; set; }
    public List<SelectListItem> Employees { set; get; }
}

это отобразит разметку HTML для элемента select с помощью multiple атрибут, который позволит пользователю выбрать несколько параметров.

@model MyViewModel
<select id="EmployeeIds" multiple="multiple" name="EmployeeIds">
    <option>Please select one</option>
    <option value="1">Shyju</option>
    <option value="2">Sean</option>
</select>

настройка выбранные параметры в multi select

подобно single select, установите EmployeeIds значение свойства для массива значений, которые вы хотите.

public IActionResult Create()
{
    var vm = new MyViewModel();
    vm.Employees = new List<SelectListItem>
    {
        new SelectListItem {Text = "Shyju", Value = "11"},
        new SelectListItem {Text = "Tom", Value = "12"},
        new SelectListItem {Text = "Jerry", Value = "13"}
    };
    vm.EmployeeIds= new int[] { 12,13} ;  
    return View(vm);
}

это позволит выбрать опцию Tom и Jerry в элементе multi select при отображении страницы.

использование ViewBag для передачи списка элементов

если вы не хотите сохранять свойство типа коллекции для передачи списка параметров в представление, вы можете использовать динамический ViewBag для этого.(это не мой лично рекомендуемый подход, поскольку viewbag динамичен, и ваш код склонен к неперехваченным ошибкам опечатки)

public IActionResult Create()
{       
    ViewBag.Employees = new List<SelectListItem>
    {
        new SelectListItem {Text = "Shyju", Value = "1"},
        new SelectListItem {Text = "Sean", Value = "2"}
    };
    return View(new MyViewModel());
}

и

<select asp-for="EmployeeId" asp-items="@ViewBag.Employees">
    <option>Please select one</option>
</select>

группировки элементов

вспомогательный метод select tag поддерживает параметры группировки в раскрывающемся списке. Все, что вам нужно сделать, это указать Group значение свойства каждого SelectListItem в методе действия.

public IActionResult Create()
{
    var vm = new MyViewModel();

    var group1 = new SelectListGroup { Name = "Dev Team" };
    var group2 = new SelectListGroup { Name = "QA Team" };

    var employeeList = new List<SelectListItem>()
    {
        new SelectListItem() { Value = "1", Text = "Shyju", Group = group1 },
        new SelectListItem() { Value = "2", Text = "Bryan", Group = group1 },
        new SelectListItem() { Value = "3", Text = "Kevin", Group = group2 },
        new SelectListItem() { Value = "4", Text = "Alex", Group = group2 }
    };
    vm.Employees = employeeList;
    return View(vm);
}

нет никаких изменений в код вида. помощник select tag теперь отобразит параметры внутри 2 optgroup предметы.


Я создал интерфейс и <options> tag helper для этого. Поэтому мне не пришлось преобразовывать IEnumerable<T> предметы IEnumerable<SelectListItem> каждый раз, когда я должен заполнить <select> управление.

и я думаю, что это прекрасно работает...

использование что-то вроде:

<select asp-for="EmployeeId">
    <option value="">Please select...</option>
    <options asp-items="@Model.EmployeesList" />
</select>

и чтобы заставить его работать с помощью тега вы должны реализовать этот интерфейс в классе:

public class Employee : IIntegerListItem
{
   public int Id { get; set; }
   public string FullName { get; set; }

   public int Value { return Id; }
   public string Text{ return FullName ; }
}

вот код:

в интерфейс:

public interface IIntegerListItem
{
    int Value { get; }
    string Text { get; }
}

на <options> tag helper:

[HtmlTargetElement("options", Attributes = "asp-items")]
public class OptionsTagHelper : TagHelper
{
    public OptionsTagHelper(IHtmlGenerator generator)
    {
        Generator = generator;
    }

    [HtmlAttributeNotBound]
    public IHtmlGenerator Generator { get; set; }

    [HtmlAttributeName("asp-items")]
    public object Items { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.SuppressOutput();
        // Is this <options /> element a child of a <select/> element the SelectTagHelper targeted?
        object formDataEntry;
        context.Items.TryGetValue(typeof(SelectTagHelper), out formDataEntry);

        var selectedValues = formDataEntry as ICollection<string>;
        var encodedValues = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
        if (selectedValues != null && selectedValues.Count != 0)
        {
            foreach (var selectedValue in selectedValues)
            {
                encodedValues.Add(Generator.Encode(selectedValue));
            }
        }

        IEnumerable<SelectListItem> items = null;
        if (Items != null)
        {
            if (Items is IEnumerable)
            {
                var enumerable = Items as IEnumerable;
                if (Items is IEnumerable<SelectListItem>)
                    items = Items as IEnumerable<SelectListItem>;
                else if (Items is IEnumerable<IIntegerListItem>)
                    items = ((IEnumerable<IIntegerListItem>)Items).Select(x => new SelectListItem() { Selected = false, Value = ((IIntegerListItem)x).Value.ToString(), Text = ((IIntegerListItem)x).Text });
                else
                    throw new InvalidOperationException(string.Format("The {2} was unable to provide metadata about '{1}' expression value '{3}' for <options>.",
                        "<options>",
                        "ForAttributeName",
                        nameof(IModelMetadataProvider),
                        "For.Name"));
            }
            else
            {
                throw new InvalidOperationException("Invalid items for <options>");
            }

            foreach (var item in items)
            {
                bool selected = (selectedValues != null && selectedValues.Contains(item.Value)) || encodedValues.Contains(item.Value);
                var selectedAttr = selected ? "selected='selected'" : "";

                if (item.Value != null)
                    output.Content.AppendHtml($"<option value='{item.Value}' {selectedAttr}>{item.Text}</option>");
                else
                    output.Content.AppendHtml($"<option>{item.Text}</option>");
            }
        }
    }
}

может быть какая-то опечатка, но цель ясна, я думаю. Мне пришлось немного отредактировать.


вы также можете использовать IHtmlHelper.GetEnumSelectList.

    // Summary:
    //     Returns a select list for the given TEnum.
    //
    // Type parameters:
    //   TEnum:
    //     Type to generate a select list for.
    //
    // Returns:
    //     An System.Collections.Generic.IEnumerable`1 containing the select list for the
    //     given TEnum.
    //
    // Exceptions:
    //   T:System.ArgumentException:
    //     Thrown if TEnum is not an System.Enum or if it has a System.FlagsAttribute.
    IEnumerable<SelectListItem> GetEnumSelectList<TEnum>() where TEnum : struct;

вы можете использовать ниже код множественный выбор:

<select asp-for="EmployeeId"  multiple="multiple" asp-items="@ViewBag.Employees">
    <option>Please select</option>
</select>

вы также можете использовать:

<select id="EmployeeId" name="EmployeeId"  multiple="multiple" asp-items="@ViewBag.Employees">
        <option>Please select</option>
    </select>

В Get : // ПОЛУЧИТЬ: public IActionResult создать() {

        ViewData["Tags"] = new SelectList(_context.Tags, "Id", "Name");

        return View();
    }

В Должности : var selectedIds= запрос.Форма ["Теги"];

В Виде :

                            <label>Tags</label>
                            <select  asp-for="Tags"  id="Tags" name="Tags" class="form-control" asp-items="ViewBag.Tags" multiple></select>