首页 > 解决方案 > ASP.NET MVC 绑定 Razor @for 循环中对象列表的唯一单选按钮,只允许选择一个

问题描述

我有一个这样的模型:

public class ImageFileDetail {
    public HttpPostedFileBase File { get; set; }
    public bool IsMainImage { get; set; }
    public string SourceURL { get; set; }
}

我用计数为 10 的 a 填充剃刀视图List<ImageFileDetail>,允许用户上传 10 张图像。只有一个图像可以是IsMainImage.

在此处输入图像描述

我必须在@for循环而不是循环中执行此操作@foreach,否则模型绑定器不会绑定到列表中的每个单独对象。发布表单时,执行 a@foreach会使它们都相同name=,因此我无法将其作为单独的对象进行迭代。

看法:

@for (var i = 0; i < Model.ImageFileDetails.Count(); i++)
{
    <tr>
        <td>
            @Html.TextBoxFor(x => x.ImageFileDetails[i].File, new { type = "file" })
        </td>
        <td>
            @Html.EditorFor(x => x.ImageFileDetails[i].SourceURL, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(x => x.ImageFileDetails[i].SourceURL, "", new { @class = "text-danger" })
        </td>
        <td>
            @*Html.EditorFor(x => x.ImageFileDetails[i].IsMainImage)*@
            // this is the radio button
            @Html.RadioButton("UniqueIsMainImage", Model.ImageFileDetails[i].IsMainImage)
            @Html.ValidationMessageFor(x => x.ImageFileDetails[i].IsMainImage, "", new { @class = "text-danger" })
        </td>
    </tr>
}

通过在 中为单选按钮提供相同的名称@RadioButton,这允许我只选择一个,这很好。当一个被选中时,前一个被取消,这是想要的结果。

问题是POST,我没有得到true列表中选定单选按钮的值,我不知道为什么。

我究竟做错了什么?

标签: asp.net-mvcfor-looprazormodel-binding

解决方案


我必须将单选按钮更改为@Html.RadioButtonFor(x => Model.SelectedImageId, Model.ImageFileDetails[i].Id)并为列表中的每个对象传递一个Id

视图模型:

public class ViewModel
{
    public List<ImageFileDetail> ImageFileDetails { get; set; } = new List<ImageFileDetail>();
    public int? SelectedImageId { get; set; }
}

public class ImageFileDetail {
    public int Id { get; set; } // for main image radio button
    public HttpPostedFileBase File { get; set; }
    public bool IsMainImage { get; set; }
    public string SourceURL { get; set; }
}

看法:

@for (var i = 0; i < Model.ImageFileDetails.Count(); i++)
{
    <tr>
        <td>
            @Html.TextBoxFor(x => x.ImageFileDetails[i].File, new { type = "file" })
        </td>
        <td>
            @Html.EditorFor(x => x.ImageFileDetails[i].SourceURL, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(x => x.ImageFileDetails[i].SourceURL, "", new { @class = "text-danger" })
        </td>
        <td>
            @*Html.EditorFor(x => x.ImageFileDetails[i].IsMainImage)*@
            @Html.RadioButtonFor(x => Model.SelectedImageId, Model.ImageFileDetails[i].Id)
            @Html.ValidationMessageFor(x => x.ImageFileDetails[i].IsMainImage, "", new { @class = "text-danger" })
        </td>
    </tr>
}

然后在我的控制器中,当迭代发布的列表时,我IsMainImageSelectedImageId.

后控制器:

foreach (var fileDetail in viewModel.ImageFileDetails)
{       
        if (fileDetail.Id == viewModel.SelectedImageId)
            fileDetail.IsMainImage = true;      
}

谢谢大家对我的信任。


推荐阅读