我需要一些帮助与选择标签助手在ASP。净的核心。

我有一个员工列表,我试图将其绑定到一个选择标记帮助程序。我的员工在List<Employee> EmployeesList中,所选值将进入EmployeeId属性。我的视图模型是这样的:

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

我的员工类是这样的:

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

我的问题是,我如何告诉我的选择标记助手使用Id作为值,同时在下拉列表中显示FullName ?

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

如果你能帮我,我会很感激的。谢谢。


当前回答

我下面的回答不能解决问题,但它与。

如果有人使用枚举而不是类模型,就像这个例子:

public enum Counter
{
    [Display(Name = "Number 1")]
    No1 = 1,
    [Display(Name = "Number 2")]
    No2 = 2,
    [Display(Name = "Number 3")]
    No3 = 3
}

和一个属性,在提交时获取值:

public int No { get; set; }

在razor页面中,您可以使用Html.GetEnumSelectList<Counter>()来获取enum属性。

<select asp-for="No" asp-items="@Html.GetEnumSelectList<Counter>()"></select>

它生成以下HTML:

<select id="No" name="No">
    <option value="1">Number 1</option>
    <option value="2">Number 2</option>
    <option value="3">Number 3</option>
</select>

其他回答

我为此创建了一个Interface和一个<options>标记帮助器。因此,我不必每次填充<select>控件时都将IEnumerable<T>项转换为IEnumerable<SelectListItem>。

我认为这很好……

用法是这样的:

<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>标记帮助器:

[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>");
            }
        }
    }
}

可能有些错别字,但我认为目的很明确。我得稍微剪辑一下。

在得到:

public IActionResult Create()
{
    ViewData["Tags"] = new SelectList(_context.Tags, "Id", "Name");
    return View();
}

在文章:

var selectedIds= Request.Form["Tags"];

视图:

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

asp-items需要一些SelectListItem类的实例集合(来自命名空间Microsoft.AspNetCore.Mvc.Rendering),其中包含文本和值属性。因此,您可以将Employees集合转换为所需的方式。Select(e => new SelectListItem)FullName, e.Id.ToString())),并将结果放到asp-items属性中。

我下面的回答不能解决问题,但它与。

如果有人使用枚举而不是类模型,就像这个例子:

public enum Counter
{
    [Display(Name = "Number 1")]
    No1 = 1,
    [Display(Name = "Number 2")]
    No2 = 2,
    [Display(Name = "Number 3")]
    No3 = 3
}

和一个属性,在提交时获取值:

public int No { get; set; }

在razor页面中,您可以使用Html.GetEnumSelectList<Counter>()来获取enum属性。

<select asp-for="No" asp-items="@Html.GetEnumSelectList<Counter>()"></select>

它生成以下HTML:

<select id="No" name="No">
    <option value="1">Number 1</option>
    <option value="2">Number 2</option>
    <option value="3">Number 3</option>
</select>

你可以使用下面的代码进行多重选择:

<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>