我从事的项目需要从一系列模型值中创建一个复选框列表,然后在发布时从控制器中检索值。不幸的是,未选中的复选框不会在发布后直接发送到表单集合,并且对每个复选框进行空值测试都会导致代码笨拙且笨拙。但是事实证明,为每个SelectListItem的文本和值添加隐藏字段可以在捕捉后立即获取所选值,因此我建立了一些在网上找到的代码,用于通过TagHelper创建复选框列表。效果很好,并且我添加了注释以显示如何在视图中使用TagHelper,如何注册它以及如何在控制器中收集选定的值。希望对别人有帮助。
答案 0 :(得分:0)
/// <summary>
/// Creates a checkbox list that can be easily accessed in the model.
/// <para>Example use in view: <checkboxlist asp-items="@Model.SomeSelectList" asp-model-name="SomeSelectList" asp-container="ul" asp-item="li"></checkboxlist></para>
/// <para>Example registration in _ViewImports file: @addTagHelper *, SomeNamespace</para>
/// <para>Example of retrieving selected values from model: model.SomeSelectList.Where(sl => sl.Selected == true).Select(sl => sl.Value).ToList()</para>
/// </summary>
[HtmlTargetElement("checkboxlist", Attributes = "asp-items, asp-model-name, asp-container, asp-item")]
public class CheckboxListTagHelper : TagHelper
{
[HtmlAttributeName("asp-items")]
public IEnumerable<SelectListItem> Items { get; set; }
[HtmlAttributeName("asp-model-name")]
public string ModelName { get; set; }
[HtmlAttributeName("asp-container")]
public string Container { get; set; }
private string _containerId;
[HtmlAttributeName("asp-container-id")]
public string ContainerId
{
get { return !string.IsNullOrWhiteSpace(_containerId) ? $"id=\"{_containerId}\"" : ""; }
set { _containerId = value; }
}
private string _containerName;
[HtmlAttributeName("asp-container-name")]
public string ContainerName
{
get { return !string.IsNullOrWhiteSpace(_containerName) ? $"name=\"{_containerName}\"" : ""; }
set { _containerName = value; }
}
private string _containerClass;
[HtmlAttributeName("asp-container-class")]
public string ContainerClass
{
get { return !string.IsNullOrWhiteSpace(_containerClass) ? $"class=\"{_containerClass}\"" : ""; }
set { _containerClass = value; }
}
[HtmlAttributeName("asp-item")]
public string Item { get; set; }
private string _itemId;
[HtmlAttributeName("asp-item-id")]
public string ItemId
{
get { return !string.IsNullOrWhiteSpace(_itemId) ? $"id=\"{_itemId}\"" : ""; }
set { _itemId = value; }
}
private string _itemName;
[HtmlAttributeName("asp-item-name")]
public string ItemName
{
get { return !string.IsNullOrWhiteSpace(_itemName) ? $"id=\"{_itemName}\"" : ""; }
set { _itemName = value; }
}
private string _itemClass;
[HtmlAttributeName("asp-item-class")]
public string ItemClass
{
get { return !string.IsNullOrWhiteSpace(_itemClass) ? $"id=\"{_itemClass}\"" : ""; }
set { _itemClass = value; }
}
public override void Process(TagHelperContext context, TagHelperOutput output)
{
var sb = new StringBuilder();
sb.Append($@"<{Container} {ContainerId} {ContainerName} {ContainerClass}>");
var index = 0;
foreach (var item in Items)
{
var selected = item.Selected ? @"checked=""checked""" : "";
var disabled = item.Disabled ? @"disabled=""disabled""" : "";
sb.Append($@"<{Item} {ItemId} {ItemName} {ItemClass}>");
sb.Append($@"<input type=""checkbox"" {selected} {disabled} id=""{ModelName}_{index}__Selected"" name=""{ModelName}[{index}].Selected"" value=""true"" /> ");
sb.Append($@"<label for=""{ModelName}_{index}__Selected"">{item.Text}</label>");
sb.Append($@"<input type=""hidden"" id=""{ModelName}_{index}__Text"" name=""{ModelName}[{index}].Text"" value=""{item.Text}"">");
sb.Append($@"<input type=""hidden"" id=""{ModelName}_{index}__Value"" name=""{ModelName}[{index}].Value"" value=""{item.Value}"">");
sb.Append($@"</{Item}>");
index++;
}
sb.Append($@"</{Container}>");
output.Content.AppendHtml(sb.ToString());
}
}
我的新项目使用了完整的.NET Framework,由于某种原因它不支持TagHelpers,因此我为SelectListItem集合创建了一个扩展方法。这是我上面发布的TagHelper类的精简版本,因为我不需要所有麻烦。我正在使用Bootstrap 3.4.1在使用此扩展方法的页面上进行脚手架安装,因此我使用了默认的div容器,其类别为“ form-check”。这是扩展方法的代码:
public static string GenerateCheckboxList(this List<SelectListItem> selectListItems, string modelName)
{
var sb = new StringBuilder();
var index = 0;
foreach (var item in selectListItems)
{
var selected = item.Selected ? @"checked=""checked""" : "";
var disabled = item.Disabled ? @"disabled=""disabled""" : "";
sb.Append($@"<div class=""form-check"">");
sb.Append($@"<label for=""{modelName}_{index}__Selected"">{item.Text}</label> ");
sb.Append($@"<input type=""checkbox"" {selected} {disabled} id=""{modelName}_{index}__Selected"" name=""{modelName}[{index}].Selected"" value=""true"" class=""form-check-input"" />");
sb.Append($@"<input type=""hidden"" id=""{modelName}_{index}__Text"" name=""{modelName}[{index}].Text"" value=""{item.Text}"">");
sb.Append($@"<input type=""hidden"" id=""{modelName}_{index}__Value"" name=""{modelName}[{index}].Value"" value=""{item.Value}"">");
sb.Append($@"</div>");
index++;
}
return sb.ToString();
}
我忘了说...在视图中渲染生成的字符串时,您需要包括一个调用以渲染原始内容,否则渲染引擎将对HTML进行编码,并且看起来很奇怪。这就是视图中所需的全部内容:
@Html.Raw(Model.CheckboxList)