ASP.NET Razor @for 循环中对象列表的 MVC 绑定唯一单选按钮,只允许选择一个
ASP.NET MVC Binding unique radio button for list of objects in Razor @for loop, allowing only one to be selected
我有这样的模型:
public class ImageFileDetail {
public HttpPostedFileBase File { get; set; }
public bool IsMainImage { get; set; }
public string SourceURL { get; set; }
}
我用计数为 10 的 List<ImageFileDetail>
填充剃刀视图,允许用户上传 10 张图像。
IsMainImage
.
只能一张图片
我必须在 @for
循环而不是 @foreach
中执行此操作,否则模型绑定器不会绑定到列表中的每个单独对象。执行 @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
,我不确定为什么。
我做错了什么?
我必须将单选按钮更改为 @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>
}
然后在我的控制器中,当遍历发布的列表时,我将 SelectedImageId
的 IsMainImage
设置为 true。
Post 控制器:
foreach (var fileDetail in viewModel.ImageFileDetails)
{
if (fileDetail.Id == viewModel.SelectedImageId)
fileDetail.IsMainImage = true;
}
感谢大家对我的信任
这可能不完全是您要查找的内容,但与您的 for/foreach 声明有关 - 如果您愿意,razor 实际上会为您执行此操作:
另外我认为你应该使用 RadioButtonFor。
您可以利用 razor 视图中的模板,让它为您处理 list/array。所以而不是:
@Html.EditorFor(x => x.ImageFileDetails[i].SourceURL,...
您应该这样做(注意模板文件的名称应与 TYPE 名称匹配):
@Html.EditorFor(x => x.ImageFileDetails)
然后创建一个 EditorTemplates/ImageFileDetail.cshtml 模板:
@model <namespace>.ImageFileDetail
<tr>
<td>
@Html.TextBoxFor(x => x.File, new { type = "file" })
</td>
<td>
@Html.EditorFor(x => x.SourceURL, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(x => x.SourceURL, "", new { @class = "text-danger" })
</td>
<td>
@*Html.EditorFor(x => x.IsMainImage)*@
// this is the radio button
@Html.RadioButtonFor(x => x.IsMainImage, x.IsMainImage, new { name = "UniqueIsMainImage" })
@Html.ValidationMessageFor(x => x.IsMainImage, "", new { @class = "text-danger" })
</td>
</tr>
我有这样的模型:
public class ImageFileDetail {
public HttpPostedFileBase File { get; set; }
public bool IsMainImage { get; set; }
public string SourceURL { get; set; }
}
我用计数为 10 的 List<ImageFileDetail>
填充剃刀视图,允许用户上传 10 张图像。
IsMainImage
.
我必须在 @for
循环而不是 @foreach
中执行此操作,否则模型绑定器不会绑定到列表中的每个单独对象。执行 @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
,我不确定为什么。
我做错了什么?
我必须将单选按钮更改为 @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>
}
然后在我的控制器中,当遍历发布的列表时,我将 SelectedImageId
的 IsMainImage
设置为 true。
Post 控制器:
foreach (var fileDetail in viewModel.ImageFileDetails)
{
if (fileDetail.Id == viewModel.SelectedImageId)
fileDetail.IsMainImage = true;
}
感谢大家对我的信任
这可能不完全是您要查找的内容,但与您的 for/foreach 声明有关 - 如果您愿意,razor 实际上会为您执行此操作:
另外我认为你应该使用 RadioButtonFor。
您可以利用 razor 视图中的模板,让它为您处理 list/array。所以而不是:
@Html.EditorFor(x => x.ImageFileDetails[i].SourceURL,...
您应该这样做(注意模板文件的名称应与 TYPE 名称匹配):
@Html.EditorFor(x => x.ImageFileDetails)
然后创建一个 EditorTemplates/ImageFileDetail.cshtml 模板:
@model <namespace>.ImageFileDetail
<tr>
<td>
@Html.TextBoxFor(x => x.File, new { type = "file" })
</td>
<td>
@Html.EditorFor(x => x.SourceURL, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(x => x.SourceURL, "", new { @class = "text-danger" })
</td>
<td>
@*Html.EditorFor(x => x.IsMainImage)*@
// this is the radio button
@Html.RadioButtonFor(x => x.IsMainImage, x.IsMainImage, new { name = "UniqueIsMainImage" })
@Html.ValidationMessageFor(x => x.IsMainImage, "", new { @class = "text-danger" })
</td>
</tr>