asp.net-mvc-3 - 使用辅助方法在 MVC3/Razor 中对 DropDownList 进行排序的最佳方法

标签 asp.net-mvc-3 razor drop-down-menu

嗨,我对 MVC3 和 Razor 还很陌生,过去几天我一直在努力理解它。我的项目架构师给我一项任务,创建一个辅助方法,对 MVC View 中的下拉列表进行排序。我有一个从 Controller 检索各种数据的 View ,并且我正在返回一些我希望出现在下拉列表中的值。我被告知不要在 Controller 中对其进行排序,并将我们想要排序的字段传递到辅助方法中。我可以像下面这样做,但架构师希望保持 View 不受 C 尖锐代码的影响:

@Html.DropDownListFor(model => model.StudyName, new SelectList(ViewBag.StudyTypes, "Value", "Text").OrderBy(l => l.Text))

所以我创建了一些示例代码和一些扩展方法来尝试让它工作。我的想法是复制现有的 Html.DropDownList 方法并允许传递“object htmlAttributes”,以便我可以将样式设置为方法调用的一部分。

这是到目前为止我的代码。我正在编辑 Controller 方法中的 ViewBag.StudyTypes 中返回下拉列表的数据:

public ActionResult Edit(int id)
{
    IEnumerable<SelectListItem> mySelectList = new List<SelectListItem>();
    IList<SelectListItem> myList = new List<SelectListItem>();

    for (int i = 0; i < 5; i++)
    {
        myList.Add(new SelectListItem() 
            { Value = i.ToString(), Text = "My Item " + i.ToString(), Selected = i == 2 }
        );
    }

    mySelectList = myList;
    ViewBag.StudyTypes = mySelectList;

    StudyDefinition studydefinition = db.StudyDefinitions.Find(id);

    return View(studydefinition);
}

这是我的查看代码:

    @model MyStudyWeb.Models.StudyDefinition

@using MyStudyWeb.Helpers

@{
    ViewBag.Mode = "Edit";
}
<div>
    @Html.DropDownListSorted(new SelectList(ViewBag.StudyTypes, "Value", "Text"))<br />
    @Html.DropDownListSorted("MyList", new SelectList(ViewBag.StudyTypes, "Value", "Text"))<br />
</div>

最后,下面是我尝试使用的扩展方法。第一个扩展方法不执行任何操作,我只是在 View 中的该点处得到一个空白区域。第二种方法可行,但很难看。对于第三种方法,我不知道如何指定“order by”参数,因为 IEnumerable 上的 OrderBy 需要 Linq 表达式。

namespace StudyDefinition.Helpers
{
    public static class HtmlHelperExtensions
    {
        // 1st sort method: sort the passed in list and return a new sorted list
        public static SelectList DropDownListSorted(this HtmlHelper helper, IEnumerable<SelectListItem> selectList)
        {
            var x = new SelectList(selectList.ToList()).OrderBy(l => l.Text);

            return x as SelectList;
        }

        // 2nd sort method: return IHtml string and create <select> list manually
        public static IHtmlString DropDownListSorted(this HtmlHelper helper, string name, SelectList selectList)
        {
            StringBuilder output = new StringBuilder();
            (selectList).OrderBy(l => l.Text);

            output.Append("<select id=" + name + " name=" + name + ">");

            foreach (var item in selectList)
            {
                output.Append("<option value=" + item.Value.ToString() + ">" + item.Text + "</option>");
            }

            output.Append("</select>");

            return MvcHtmlString.Create(output.ToString());
        }

        // 3rd sort method: pass in order by parameter - how do I use this?
        public static IHtmlString DropDownListSorted(this HtmlHelper helper, string name, SelectList selectList, string orderBy)
        {
            StringBuilder output = new StringBuilder();

            //How do I use the orderBy parameter?
            (selectList).OrderBy(l => l.Text);

            output.Append("<select id=" + name + " name=" + name + ">");

            foreach (var item in selectList)
            {
                output.Append("<option value=" + item.Value.ToString() + ">" + item.Text + "</option>");
            }

            output.Append("</select>");

            return MvcHtmlString.Create(output.ToString());
        }        
    }
}

我真的不知道该采取什么最好的方法,可能有一种更简单的方法,但我完全不知道,而且我可能已经到了见树不见林的地步了。一些问题

  • 我应该返回 SelectList 或 MvcHtmlString,还是完全其他的东西?

  • 对于第一个扩展方法,如何获取返回的 SelectList 以在 View 中呈现?

  • 如何将指定排序顺序的参数传递给扩展方法?

  • 如何传递“object htmlAttributes”参数,以及如何将此对象/参数应用到 SelectList?

如果有人有一些想法或建议,我会很感激一些反馈:)

最佳答案

代码的第一个也是最重要部分是摆脱任何ViewBag/ViewData(我个人认为这是 MVC 应用程序的癌症)并使用 View 模型和强类型 View 。

因此,让我们首先定义一个 View 模型,该模型代表我们的 View 将使用的数据(本例中为 dropdownlistg):

public class MyViewModel
{
    public string SelectedItem { get; set; }
    public IEnumerable<SelectListItem> Items { get; set; }
}

那么我们就可以有一个 Controller :

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var model = new MyViewModel
        {
            // I am explicitly putting some items out of order
            Items = new[]
            {
                new SelectListItem { Value = "5", Text = "Item 5" },
                new SelectListItem { Value = "1", Text = "Item 1" },
                new SelectListItem { Value = "3", Text = "Item 3" },
                new SelectListItem { Value = "4", Text = "Item 4" },
            }
        };
        return View(model);
    }
}

和 View :

@model MyViewModel
@Html.DropDownListForSorted(
    x => x.SelectedItem, 
    Model.Items, 
    new { @class = "foo" }
)

最后一个是辅助方法,它将按值对下拉列表进行排序(您可以调整它以按文本排序):

public static class HtmlExtensions
{
    public static IHtmlString DropDownListForSorted<TModel, TProperty>(
        this HtmlHelper<TModel> helper, 
        Expression<Func<TModel, TProperty>> expression, 
        IEnumerable<SelectListItem> items, 
        object htmlAttributes
    )
    {
        var model = helper.ViewData.Model;
        var orderedItems = items.OrderBy(x => x.Value);
        return helper.DropDownListFor(
            expression, 
            new SelectList(orderedItems, "Value", "Text"), 
            htmlAttributes
        );
    }
}

关于asp.net-mvc-3 - 使用辅助方法在 MVC3/Razor 中对 DropDownList 进行排序的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7223185/

相关文章:

asp.net-mvc-3 - Ninject 和 Entity Framework

asp.net-mvc - 如何在 Razor 中设置数字编辑器的最小值、最大值和默认值

jquery - 单击页面上其他位置后如何隐藏 Bootstrap 打开的折叠菜单

c# - 使用 Razor 内联设置 javascript 变量,这是好的做法/安全吗?

asp.net-mvc-3 - Telerik MVC 网格。在客户端分组

jquery - 浏览器问题的多个打开选项卡的客户端脚本变量范围

带有箭头的 jQuery 切换下拉菜单

javascript - 无法更新 Material UI 下拉列表中选定的选项

asp.net-mvc - 找不到类型或命名空间名称 'DbContext'

c# - 限制 View 中的内联代码具有与模型相关的代码以外的代码