繁体   English   中英

MVC4:从自定义类填充下拉列表

[英]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还使用一个属性作为文本键,一个属性作为值键。 在您的情况下,这显然会产生问题,因为您希望将CodeSource组合在一起以形成文本键。 为了解决这个问题,您需要在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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM