Best way to sort DropDownList in MVC3 / Razor using helper method

Hi, that's why I'm pretty new to MVC3 and Razor, and I have been trying to trick him in the last few days. My project architect was tasked with creating a helper method that sorts a drop-down list in an MVC view. I have a view that retrieves various data from the controller, and I am returning some values ​​that I want to display in the drop down list. I was told not to sort it in the controller, and also to pass the field that we want to sort into a helper method. I could do this as shown below, but the architect wants to keep the view without clear code:

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

So, I created a code sample and some extension methods to try to make it work. My idea is to replicate an existing Html.DropDownList method and allow the transfer of "object htmlAttributes" so that I can set the style as part of the method call.

Here is my code so far. I am returning data for a dropdown in the ViewBag.StudyTypes in the Edit Controller method:

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);
}

Here is my view code:

    @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>

Finally, below are the extension methods I'm trying to get. The first extension method does nothing, I just get empty space at this point in the view. The second method seems to work, but it is ugly. For the third method, I don’t know how to specify the "order by" parameter, since OrderBy in IEnumerable expects a Linq expression.

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 ?

  • , ?

  • 'object htmlAttributes' / SelectList?

- - , :)

+5
3

ViewBag/ViewData ( MVC), .

, , , ( dropdownlistg):

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

:

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);
    }
}

:

@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
        );
    }
}
+5

,

using (BDMMContext dataContext = new BDMMContext())
{
foreach (Arquiteto arq in dataContext.Arquitetos.SqlQuery("SELECT * FROM  Arquitetos ORDER BY Nome"))
                    {
                        SelectListItem selectItem = new SelectListItem { Text = arq.Nome, Value = arq.Arquiteto_Id.ToString() };
                        //
                        list.Add(selectItem);
                    }
}
0

, .

:

: StudyViewModel.cs

public class StudyViewModel {
    public string StudyName { get; set; }
    public string StudyTypes { get; set; }
}

: StudyController.cs

using System.Web.Mvc;
public class StudyController 
{
    public List<SelectListItem> studyTypes() 
    {
        List<SelectListItem> itemList = new List<SelectListItem>();
        for (var i=0; i<5; i++)
        {
            itemList.Add = new SelectListItem({
                Value = i.ToString();
                Text = "My Item";
            });
        }
        // You can sort here....
        List<SelectListItem> sortedList = itemList.OrderBy(x=>x.Text);
        return sortedList;
    }

    public ActionResult Edit(int id)
    {
        //You won't need this because you get it using your
        //controller routine, instead 
        //ViewBag.StudyTypes = studySlots.OrderBy(e => e.Value);

        //-- unless you need to add these values to the model for 
        // some reason (outside of filling the ddl), in which case....
        // StudyViewModel svm = new StudyViewModel();
        // svm.StudyTypes = studySlots.OrderBy(e => e.Value);
        // svm.StudyName = "My Item";
        // return View(svm);

        // Otherwise, just....
        return View();
    }
}

: Edit.cshtml

@Html.DropDownListFor(model => model.StudyName)
    .OptionLabel('Select...')
    .DataTextField('Text')
    .DataValueField('Value')
    .Datasource(source => 
    {
       // This is where you populate your data from the controller
        source.Read(read => 
        {
            read.Action("studyTypes", "Study");
        });
    })
    .Value(Model.StudyName != null ? Model.StudyName.ToString() : "")
)

This way you can avoid ViewBags and just use the function to populate the values ​​directly.

0
source

All Articles