从List <SelectListItem>集合创建复选框列表

时间:2019-12-10 22:35:59

标签: checkboxlist asp.net-core-tag-helpers

我从事的项目需要从一系列模型值中创建一个复选框列表,然后在发布时从控制器中检索值。不幸的是,未选中的复选框不会在发布后直接发送到表单集合,并且对每个复选框进行空值测试都会导致代码笨拙且笨拙。但是事实证明,为每个SelectListItem的文本和值添加隐藏字段可以在捕捉后立即获取所选值,因此我建立了一些在网上找到的代码,用于通过TagHelper创建复选框列表。效果很好,并且我添加了注释以显示如何在视图中使用TagHelper,如何注册它以及如何在控制器中收集选定的值。希望对别人有帮助。

1 个答案:

答案 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)