[英]MVC4: populate a drop down list from a custom class
I have a class that I populate when a user navigates to a certain page, /Home/About, within my MVC4 application. 我有一个类,当用户导航到我的MVC4应用程序中的某个页面/ Home / About时,我会填充该类。 I populate a class with data and I would like to have in my view that data in a drop down list.
我用数据填充一个类,我希望在我的视图中有一个下拉列表中的数据。
My class looks like this: (UPDATED) 我的课看起来像这样:(更新)
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;
}
}
How do I take this populated List of type WorkSection and make that the data source for my drop down list? 如何使用此填充的WorkSection类型列表并将其作为我的下拉列表的数据源? I would like to display the Code and Source field in a concatenated fashion, like "Code:Source" within the drop down list with the ID as the selected item's value.
我想以连接的方式显示代码和源字段,例如下拉列表中的“代码:源”,ID作为所选项的值。
UPDATE for ActionResult, where code will be called from on /Home/About 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);
}
First up, we need a view model to encapsulate the data for the view: 首先,我们需要一个视图模型来封装视图的数据:
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
}
Next up, we need a way to populate the SelectList
. 接下来,我们需要一种方法来填充
SelectList
。 I wrote a custom method a while ago to do just that: 我刚才写了一个自定义方法来做到这一点:
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);
}
This uses expression trees for type-safety, ensuring problems are caught at compile-time, rather than run-time. 这使用表达式树来实现类型安全,确保在编译时捕获问题,而不是在运行时捕获。
SelectList
also uses one property for the text key and one for the value key. SelectList
还使用一个属性作为文本键,一个属性作为值键。 In your situation, this obviously creates a problem, because you want to combine Code
and Source
to form the text key. 在您的情况下,这显然会产生问题,因为您希望将
Code
和Source
组合在一起以形成文本键。 In order to get around that, you'll need to create a new property in WorkSection
that combines both: 为了解决这个问题,您需要在
WorkSection
中创建一个结合了以下两者的新属性:
public string CodeSource
{
get { return this.Code + ":" + this.Source; }
}
That way, you can use that to create the SelectList
as normal. 这样,您可以使用它来正常创建
SelectList
。 To do that, your action might like something like: 要做到这一点,你的行动可能会像:
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);
}
You can use that in the view like so: 您可以在视图中使用它,如下所示:
@Html.DropDownListFor(m => m.WorkSectionId, Model.WorkSections, "--Please Select--")
@Html.ValidationMessageFor(m => m.WorkSectionId)
One final note on BuildSelectList
. 关于
BuildSelectList
最后一点说明。 The method has saved me a lot of time when dealing with dropdowns in general. 一般来说,这种方法在处理下拉菜单时节省了很多时间。 So much so that I now define it as a public method on a base controller, which I then derive all of my controllers from.
这么多,我现在将它定义为基本控制器上的公共方法,然后我从中派生出所有控制器。 However, if you want to do that, you'll want to mark it with the
[NonAction]
attribute so it doesn't interfere with routing. 但是,如果要执行此操作,则需要使用
[NonAction]
属性对其进行标记,以使其不会干扰路由。
Update per comments 每条评论更新
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);
}
}
Then you'd derive your controllers from BaseController
instead: 然后你将从
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.