1

当用户导航到我的 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 的更新,将从 /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);
    }
4

2 回答 2

2

首先,我们需要一个视图模型来封装视图的数据:

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
{
    // 
}
于 2013-11-12T01:43:52.240 回答
1

@Hmtl.DropdownListFor(m=>m.YourNameForSelectedWorkSectionId, Model.WorkSections.Select(x => new SelectListItem { Text = x.Code +":"+x.Source, Value = x.ID}))

于 2013-11-12T01:41:11.667 回答