[英]MVC4: populate a drop down list from a custom class
我有一个类,当用户导航到我的MVC4应用程序中的某个页面/ Home / About时,我会填充该类。 我用数据填充一个类,我希望在我的视图中有一个下拉列表中的数据。
我的课看起来像这样:(更新)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
public class WorkSection : List<WorkSection>
{
[Required]
[Display(Name = "WorkSection")]
public int ID { get; set; }
public string Code { get; set; }
public SelectList WorkSections { get; set; }
public WorkSection()
{
// Default Constructor
}
public WorkSection(int id, string code)
{
this.ID = ws_id;
this.Code = code;
}
}
如何使用此填充的WorkSection类型列表并将其作为我的下拉列表的数据源? 我想以连接的方式显示代码和源字段,例如下拉列表中的“代码:源”,ID作为所选项的值。
ActionResult的UPDATE,其中代码将从/ Home / About调用
public ActionResult About()
{
WorkSection model = new WorkSection();
OracleConnection con = new OracleConnection();
con.ConnectionString = "omitted";
try
{
con.Open();
}
catch (Exception ex)
{
throw ex;
}
try
{
OracleDataReader reader = null;
// Work Section
OracleCommand cmd = new OracleCommand("SELECT ID, CODE FROM MyTable ORDER BY CODE", con);
reader = cmd.ExecuteReader();
while (reader.Read())
{
model.Add(new WorkSection()
{
ID = Int16.Parse(reader["ID"].ToString()),
Code = reader["CODE"].ToString()
});
}
model.WorkSections = BuildSelectList(model.WorkSections, m => m.ID, m => m.Code);
con.Close();
con.Dispose();
}
catch (Exception ex)
{
throw ex;
}
return View(model);
}
首先,我们需要一个视图模型来封装视图的数据:
public class TestViewModel
{
[Required]
[Display(Name = "Work section")]
// This represents the selected ID on the dropdown
public int WorkSectionId { get; set; }
// The dropdown itself
public SelectList WorkSections { get; set; }
// other properties
}
接下来,我们需要一种方法来填充SelectList
。 我刚才写了一个自定义方法来做到这一点:
private SelectList BuildSelectList<TSource>(IEnumerable<TSource> source,
Expression<Func<TSource, int>> valueKey, Expression<Func<TSource, string>> textKey,
object selectedValue = null)
{
var selectedValueKey = ((MemberExpression)(MemberExpression)valueKey.Body).Member.Name;
var selectedTextKey = ((MemberExpression)(MemberExpression)textKey.Body).Member.Name;
return new SelectList(source, selectedValueKey, selectedTextKey, selectedValue);
}
这使用表达式树来实现类型安全,确保在编译时捕获问题,而不是在运行时捕获。 SelectList
还使用一个属性作为文本键,一个属性作为值键。 在您的情况下,这显然会产生问题,因为您希望将Code
和Source
组合在一起以形成文本键。 为了解决这个问题,您需要在WorkSection
中创建一个结合了以下两者的新属性:
public string CodeSource
{
get { return this.Code + ":" + this.Source; }
}
这样,您可以使用它来正常创建SelectList
。 要做到这一点,你的行动可能会像:
public ActionResult Index()
{
var workSections = // ... fetch from database
TestViewModel model = new TestViewModel();
model.WorkSections = BuildSelectList(workSections, m => m.ID, m => m.CodeSource);
return View(model);
}
您可以在视图中使用它,如下所示:
@Html.DropDownListFor(m => m.WorkSectionId, Model.WorkSections, "--Please Select--")
@Html.ValidationMessageFor(m => m.WorkSectionId)
关于BuildSelectList
最后一点说明。 一般来说,这种方法在处理下拉菜单时节省了很多时间。 这么多,我现在将它定义为基本控制器上的公共方法,然后我从中派生出所有控制器。 但是,如果要执行此操作,则需要使用[NonAction]
属性对其进行标记,以使其不会干扰路由。
每条评论更新
public class BaseController : Controller
{
[NonAction]
public SelectList BuildSelectList<TSource>(IEnumerable<TSource> source,
Expression<Func<TSource, int>> valueKey, Expression<Func<TSource, string>> textKey,
object selectedValue = null)
{
var selectedValueKey = ((MemberExpression)(MemberExpression)valueKey.Body).Member.Name;
var selectedTextKey = ((MemberExpression)(MemberExpression)textKey.Body).Member.Name;
return new SelectList(source, selectedValueKey, selectedTextKey, selectedValue);
}
}
然后你将从BaseController
派生你的控制器:
public HomeController : BaseController
{
//
}
@Hmtl.DropdownListFor(m=>m.YourNameForSelectedWorkSectionId, Model.WorkSections.Select(x => new SelectListItem { Text = x.Code +":"+x.Source, Value = x.ID}))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.