在ASP.NET Core MVC中select标签助手
我需要帮助ASP.NET Core中的select标签助手。
我有一个员工名单,我试图绑定到一个select标签助手。 我的员工在一个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; } }
我的问题是如何告诉我的select标签助手使用Id
作为值,同时在下拉列表中显示FullName
?
<select asp-for="EmployeeId" asp-items="???" />
我会很感激这个帮助。 谢谢。
使用Select Tag帮助器在视图中呈现SELECT元素
在您的GET操作中,创build视图模型的对象,加载EmployeeList
集合属性并将其发送到视图。
public IActionResult Create() { var vm = new MyViewModel(); vm.EmployeesList = new List<Employee> { new Employee {Id = 1, FullName = "Shyju"}, new Employee {Id = 2, FullName = "Scot"} }; return View(vm); }
在你的创build视图中,从EmployeeList
属性创build一个新的SelectList
对象,并将其作为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 action方法接受提交的表单数据。
[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; } }
而在你的行动中,
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
命名空间。
使用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
属性,我使用这些属性作为我们创build的SelectList
对象的DataValueField
和DataTextField
。 您可以将硬编码列表更改为从数据库表中读取数据的代码。
视图代码将是相同的。
<select asp-for="EmployeeId" asp-items="@Model.Employees" > <option>Please select one</option> </select>
从一个string列表中呈现一个SELECT元素。
有时你可能想要从一个string列表中呈现一个select元素。 在这种情况下,您可以使用仅使用IEnumerable<T>
的SelectList
构造函数
var vm = new MyViewModel(); var items = new List<string> {"Monday", "Tuesday", "Wednesday"}; vm.Employees = new SelectList(items); return View(vm);
视图代码将是相同的。
设置选定的选项
有时候,您可能希望在SELECT元素中设置一个选项作为默认选项(例如,在编辑屏幕中,您要加载之前保存的选项值)。 为此,您可以简单地将EmployeeId
属性值设置为您想要select的选项的值。
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); }
这将在页面呈现时在select元素中selectTom选项。
多select下拉菜单
如果你想渲染一个多select下拉列表,你可以简单地将你在视图中用于asp-for
属性的视图模型属性改为数组types。
public class MyViewModel { public int[] EmployeeIds { get; set; } public List<SelectListItem> Employees { set; get; } }
这将为具有multiple
属性的select元素呈现HTML标记,这将允许用户select多个选项。
@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>
在多选中设置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); }
这将在页面呈现时在多选元素中selectTom和Jerry选项。
使用ViewBag传输项目列表
如果你不想保留一个集合types的属性来传递选项列表到视图,你可以使用dynamic的ViewBag来做到这一点 ( 这不是我个人推荐的方法,因为viewbag是dynamic的,你的代码很容易被忽略错字错误 )
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>
我为此创build了一个接口和一个<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>"); } } } }
可能有一些错字,但我认为目的很明确。 我不得不编辑一点点。
您也可以使用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>