如何在从@Html生成的选择中保持所有值.MVC.net网页中的ListBoxFor

本文关键字:MVC net ListBoxFor 网页 @Html 选择 | 更新日期: 2023-09-27 18:12:14

问题:我在HttpGet中基于数据库查询生成了一个@Html.ListBoxFor。在我的HttpPost中,我想验证是否至少选择了一个元素。如果没有,我只想添加一条验证消息。

当前结果:我收到消息"请至少选择一个项目",但现在select为空(select元素在那里,但包含0个选项(。我知道Model.Items在我的HttpPost中将为null。

问题:如何使用我的模型来持久化Model.Items以使其不为空

附加信息:我正在努力避免使用FormCollection collection和其他JavaScript。

--代码——

控制器:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        MyViewModel model = new MyViewModel
        {
            Items = Enumerable.Range(1, 5).Select(x => new SelectListItem
            {
                Value = x.ToString(),
                Text = "item " + x
            })
        };
        return View(model);
    }
    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        return View(model);
    }
}

型号:

public class MyViewModel
{
    public MyViewModel()
    {
        Items = new List<SelectListItem>();
    }

    [Required(ErrorMessage = "Please select at least one item")]
    public string[] SelectedItems { get; set; }
    public IEnumerable<SelectListItem> Items { get; set; }
}

视图:

@model ProjectGenerator.Models.MyViewModel
@using (Html.BeginForm())
{
    @Html.ListBoxFor(x => x.SelectedItems, Model.Items)
    @Html.ValidationMessageFor(x => x.SelectedItems)
    <button type="submit">OK</button>
}

如何在从@Html生成的选择中保持所有值.MVC.net网页中的ListBoxFor

    public IEnumerable<SelectListItem> Items 
    {
        get
        {            
            if (HttpContext.Current.Session["MY_ITEMS_TO_LIST_FOR"] == null)
            {
                return null;
            }
            else
            {
                return (IEnumerable<SelectListItem>)HttpContext.Current.Session["MY_ITEMS_TO_LIST_FOR"];
            }
        }
        set
        {
            if (value.Count() > 0) //http post reset value
            {
                HttpContext.Current.Session["MY_ITEMS_TO_LIST_FOR"] = value;
            }
        }
    }

我以这种方式进行了测试,效果很好。还有其他方法,但我发现这更容易。如果调试项目集items属性,您将看到,由于某些原因,即使使用session,这些项也会从http-post上的集合中删除。为了防止会话中的集合接收空集合,我使用了If(Items.Count((>0(。你可以扩大这个想法,定制你的装备。

您没有也不应该为属性Items中每个SelectListItem的每个属性创建表单控件,这样在提交时它们就不会包含在表单数据中。您需要在返回视图的POST方法中重新分配SelectList

public ActionResult Index()
{
  MyViewModel model = new MyViewModel();
  ConfigureViewModel(model);
  return View(model);
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
  if (!ModelState.IsValid)
  {
    ConfigureViewModel(model);
    return View(model);
  }
  // Save and redirect
}
private void ConfigureViewModel(MyViewModel model)
{
  model.Items = Enumerable.Range(1, 5).Select(x => new SelectListItem
  {
    Value = x.ToString(),
    Text = "item " + x
  });
}

使用Json结果和templateview的一个示例。这是一个很好的模式。

控制器(您可以将json配置为不允许get(:

   public class FornecedorController : BaseController
    {
        protected FornecedorServices Service = new FornecedorServices();
        [HttpGet]
        [Authorize(Roles = ApplicationRoles.FORNECEDOR_VISUALIZAR)]
        [OutputCache(NoStore = false, Duration = 3600)]
        public JsonResult ListarJson(FornecedorParameters parameters)
        {
            var model = this.Service.Search(parameters)
                .Select(x => new
                {
                    Value = x.Codigo,
                    Description = x.CodigoNomeFantasia
                });
            return this.Json(model, JsonRequestBehavior.AllowGet);
        }
    }

模板视图(您可以自定义自己的(:

@model int[]
@{
    var id = "id" + Guid.NewGuid().ToString().Substring(0, 5);
    var disabled = (bool)(this.ViewData["disabled"] ?? false);
    var showAll = (bool)(this.ViewData["ShowAll"] ?? false);
    var state = this.ViewData.ModelState[Html.NameFor(x => x).ToString()];
    var size = (Size)(this.ViewData["Size"] ?? Size.Big);
    string css = (state != null && state.Errors.Count > 0) ? "input-validation-error" : string.Empty;
    List<SelectListItem> listValues;
    if (this.Model == null)
    {
        listValues = new List<SelectListItem>();
    }
    else
    {
        listValues = this.Model.Select(x => new SelectListItem { Selected = true, Value = x.ToString(), Text = x.ToString() }).ToList();
    }
}
<div class="field-@size @css">
    <h3>@Html.LabelFor(model => model):</h3>
        @Html.ListBox("", listValues, new { id = id })
</div>
<script language="javascript" type="text/javascript">
    $("#@id").turnAutoComplete("@Url.Action("ListarJson", "Fornecedor", new { ShowAll = showAll })"@if (showAll) { <text>, checkSelectAll</text> })
        .change(function () {
            @Html.Raw(this.ViewData["OnChange"])
        });
</script>