Can I customise my data text field in an MVC Selec

2019-01-14 17:20发布

问题:

I am creating a SelectList from a List(T) class to use to populate a HtmlHelper.DropDownList in an MVC view, setting the dataValueField and dataTextField in the Select List constructor. The text that should be displayed doesn't excatly match one of the properties on my class and still needs to be manipulated. Is there any way of doing this through the SelectList constructor? I realise I could do this by creating a struct or class to use as the IEnumerable input for the Select list but I'd prefer not if I don't need to.

My Controller code is currently:

        var members = MemberService.GetAll();
        this.ViewData["Members"] = new SelectList(members, "Id", "Name");

My View code is currently:

        <%= Html.DropDownList("Members") %>

Instead of "Surname" as my display field I'd like to be able to preformat the field by combining (and formatting) two properties.

回答1:

You can create loop through the members list, adding the values to a new list that you then create the SelectList from. Something like:

var members = MemberService.GetAll();
List<object> newList = new List<object>();
foreach(var member in members)
    newList.Add( new { 
        Id = member.Id, 
        Name = member.Name + " " + member.Surname 
    } );
this.ViewData["Members"] = new SelectList(newList, "Id", "Name");

I can't remember if you can use an anonymous type like that or not, but if not you can create an small data class to use as an intermediary.



回答2:

You can create an extension method and set whatever you want as the text. It could be something as

public static IList<SelectListItem> ToSelectList<T>(this IEnumerable<T> itemsToMap, Func<T, string> textProperty, Func<T, string> valueProperty, Predicate<T> isSelected)
{
    var result = new List<SelectListItem>();

    foreach (var item in itemsToMap)
    {
        result.Add(new SelectListItem
        {
            Value = valueProperty(item),
            Text = textProperty(item),
            Selected = isSelected(item)
        });
    }
    return result;
}

Then you call this method as:

var membersSelectList = MemberService.GetAll().ToSelectList(m=>m.FirstName + " " + m.Surname, m.Id.ToString(), m=>m.Id < -1); //Any predicate you need here.


回答3:

For those that use LINQ. Instead of:

    var members = MemberService.GetAll();

you can use:

    ViewBag.MembersList = new SelectList(
    from x in db.members where x.role = 5 select new {x.ID, x.Name, x.Surname, S_Name = x.Surname + " " + x.Name}, 
    "ID", "S_Name");

and then use ViewBag.MemberList in your Razor code like

    @Html.DropDownList("MembersList", String.Empty)