如何在ASP.NET Core中实现复选框列表?

Arn*_*ein 30 c# asp.net-core

我希望在ASP.NET Core中实现一个checkboxlist,但我遇到了一些困难.

我的ViewModel:

public class GroupIndexViewModel
{
    public Filter[] Filters { get; set; }
}

public class Filter
{
    public int Id { get; set; }
    public string Name { get; set; }
    public bool Selected { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我的看法:

@model GroupIndexViewModel
<form asp-action="Index" asp-controller="Group" method="get">
  <ul>
  @for (var i = 0; i < Model.Filters.Length; i++)
  {
    <li>
      <input type="checkbox" id="@Model.Filters[i].Name" asp-for="@Model.Filters[i].Selected" value="@Model.Filters[i].Selected" checked="@Model.Filters[i].Selected" />
      <label for="@Model.Filters[i].Name">@Model.Filters[i].Name</label>
    </li>
  }
  </ul>
  <button type="submit" name="action">Filtrer</button>
</form>
Run Code Online (Sandbox Code Playgroud)

发布到我的控制器时,我的viewmodel中的Filter属性显示为false,即使它在视图中被选中.

dot*_*tep 38

我会按照以下方式做.

@model GroupIndexViewModel
<form asp-action="Index" asp-controller="Group" method="get">
    <ul>
        @for (var i = 0; i < Model.Filters.Count; i++)
        {
            <li>       
                <input type="checkbox" asp-for="@Model.Filters[i].Selected"  />
                <label asp-for="@Model.Filters[i].Selected">@Model.Filters[i].Name</label>
                <input type="hidden" asp-for="@Model.Filters[i].Id" />
                <input type="hidden" asp-for="@Model.Filters[i].Name" />                
            </li>
        }
    </ul>
    <button type="submit" name="action">Filtrer</button>
</form>
Run Code Online (Sandbox Code Playgroud)

在这里,我假设你有适当的控制器和动作的实现.

  • 另一个关键注意事项 - 您必须使用“for”而不是“foreach”,以便视图模型可以拾取属性名称(在本例中 - “Filter”) (3认同)

小智 15

问题可能已经得到解答,但我想解释你的问题,以便其他人能够理解正在发生的事情.

您不知道您已经false为输入指定了值,因为您实现了对属性的错误使用.

我们来看看您的观点

@model GroupIndexViewModel
<form asp-action="Index" asp-controller="Group" method="get">
   <ul>
     @for (var i = 0; i < Model.Filters.Length; i++)
     {
      <li>
        <input type="checkbox" id="@Model.Filters[i].Name" asp-for="@Model.Filters[i].Selected" value="@Model.Filters[i].Selected" checked="@Model.Filters[i].Selected" />
        <label for="@Model.Filters[i].Name">@Model.Filters[i].Name</label>
     </li>
     }
  </ul>
  <button type="submit" name="action">Filtrer</button>
</form>
Run Code Online (Sandbox Code Playgroud)

所以,首先.您正在从数组中创建输入元素Filter.现在让我们仔细看看你的输入元素.

<input type="checkbox" id="@Model.Filters[i].Name" asp-for="@Model.Filters[i].Selected" value="@Model.Filters[i].Selected" checked="@Model.Filters[i].Selected" />
Run Code Online (Sandbox Code Playgroud)

现在,让我解释一下.

  1. 您正在使用该type属性指定类型.
  2. 您正在使用该id属性指定id .
  3. 使用asp-for标记帮助器将输入绑定到模型.
  4. 您可以使用该value属性为输入指定值.
  5. 最后,使用checked属性将输入设置为checked .

如果你看一下Tag Helpers文档,你会发现.Net TypeInput Type之间的关系,理解:

复选框包含一个布尔值,对应于模型,并由标记帮助器格式化为type="checkbox".

由于您使用的是type="checkbox"属性,因此Tag Helper值只能是truefalse.因此,如果我们返回并查看input元素,您已经为输入指定了一个值.即使tag-helper可以为输入赋值,也不能覆盖已指定的值.因此,您的输入,将永远有您指定的值,在这种情况下,一个boolean始终默认为false.

现在您可能认为您的input元素有一个false值,例如,添加checked="checked" 不会更改值true,因为value属性会覆盖该checked属性.导致两个属性的错误实现.

因此,您只能使用其中一个属性.(要么是value或者checked).为方便起见,您可以使用它们.但在这种情况下,您必须使用默认checked属性.由于您正在实现Tag Helper,并且输入值必须是类型boolean.并且checked属性值返回一个布尔值,例如,是Tag Helper使用的布尔值.

所以@dotnetstep提供的实现应该可以工作,因为它只在input元素中声明了标记helper.因此Tag Helper处理输入的相应属性.

@model GroupIndexViewModel
<form asp-action="Index" asp-controller="Group" method="get">
    <ul>
        @for (var i = 0; i < Model.Filters.Count; i++)
        {
            <li>       
                <input type="checkbox" asp-for="@Model.Filters[i].Selected"  />
                <label asp-for="@Model.Filters[i].Selected">@Model.Filters[i].Name</label>
                <input type="hidden" asp-for="@Model.Filters[i].Id" />
                <input type="hidden" asp-for="@Model.Filters[i].Name" />                
            </li>
        }
    </ul>
    <button type="submit" name="action">Filtrer</button>
</form>
Run Code Online (Sandbox Code Playgroud)


gsx*_*y73 6

在@dotnetstep的答案的基础上,我创建了一个Tag Helper,它使用SelectListItemIEnumerable模型并生成他的答案中描述的字段。

这是标记帮助程序代码:

[HtmlTargetElement(Attributes = "asp-checklistbox, asp-modelname")]
public class CheckListBoxTagHelper : TagHelper
{
    [HtmlAttributeName("asp-checklistbox")]
    public IEnumerable<SelectListItem> Items { get; set; }

    [HtmlAttributeName("asp-modelname")]
    public string ModelName { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        var i = 0;
        foreach (var item in Items)
        {
            var selected = item.Selected ? @"checked=""checked""" : "";
            var disabled = item.Disabled ? @"disabled=""disabled""" : "";

            var html = $@"<label><input type=""checkbox"" {selected} {disabled} id=""{ModelName}_{i}__Selected"" name=""{ModelName}[{i}].Selected"" value=""true"" /> {item.Text}</label>";
            html += $@"<input type=""hidden"" id=""{ModelName}_{i}__Value"" name=""{ModelName}[{i}].Value"" value=""{item.Value}"">";
            html += $@"<input type=""hidden"" id=""{ModelName}_{i}__Text"" name=""{ModelName}[{i}].Text"" value=""{item.Text}"">";

            output.Content.AppendHtml(html);

            i++;
        }

        output.Attributes.SetAttribute("class", "th-chklstbx");
    }
}
Run Code Online (Sandbox Code Playgroud)

您将需要在_ViewImports.cshtml文件中添加以下内容:

@addTagHelper *, <ProjectName>
Run Code Online (Sandbox Code Playgroud)

然后,将复选框列表放到剃刀视图中,就像这样简单:

<div asp-checklistbox="Model.Brands" asp-modelname="Brands"></div>
Run Code Online (Sandbox Code Playgroud)

您可能会注意到,我在div中添加了class属性,以对框及其内容进行样式设置。这是CSS:

.th-chklstbx {
  border: 1px solid #ccc;
  padding: 10px 15px;
  -webkit-border-radius: 5px ;
  -moz-border-radius: 5px ;
  -ms-border-radius: 5px ;
  border-radius: 5px ; 
}
.th-chklstbx label {
    display: block;
    margin-bottom: 10px; 
}
Run Code Online (Sandbox Code Playgroud)