如何在 MVC.net 网页中保留由 @Html.ListBoxFor 生成的 select 中的所有值?
How persist all values in a select made from @Html.ListBoxFor in a MVC.net web page?
问题:我根据 HttpGet 中的数据库查询生成 @Html.ListBoxFor
。在我的 HttpPost 期间,我想验证至少一个元素已被 selected。如果没有,我只想添加一条验证消息。
当前结果:我收到消息 "Please select at least one item" 但现在 Select 是空白的(select 元素在那里但包含 0 个选项)。我知道 Model.Items
在我的 HttpPost 中将为空。
问题:如何使用我的模型持久化 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>
}
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 属性 ,
您会看到由于某种原因,这些项目已从 http post 上的集合中删除,即使您使用 session.
为了防止会话中的集合接收到空集合,我使用了 If (Items.Count()> 0)。
您可以扩大这个想法并自定义您的 get 和 set。
您没有,也不应该为 属性 Items
中每个 SelectListItem
的每个 属性 创建表单控件,因此它们不包含在表单中提交时的数据。您需要在 return 视图
的 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 结果和模板视图的示例。这是一个很好的模式。
控制器(你可以配置json不允许获取):
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>
问题:我根据 HttpGet 中的数据库查询生成 @Html.ListBoxFor
。在我的 HttpPost 期间,我想验证至少一个元素已被 selected。如果没有,我只想添加一条验证消息。
当前结果:我收到消息 "Please select at least one item" 但现在 Select 是空白的(select 元素在那里但包含 0 个选项)。我知道 Model.Items
在我的 HttpPost 中将为空。
问题:如何使用我的模型持久化 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>
}
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 属性 , 您会看到由于某种原因,这些项目已从 http post 上的集合中删除,即使您使用 session. 为了防止会话中的集合接收到空集合,我使用了 If (Items.Count()> 0)。 您可以扩大这个想法并自定义您的 get 和 set。
您没有,也不应该为 属性 Items
中每个 SelectListItem
的每个 属性 创建表单控件,因此它们不包含在表单中提交时的数据。您需要在 return 视图
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 结果和模板视图的示例。这是一个很好的模式。
控制器(你可以配置json不允许获取):
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>