Como posso adicionar um item a uma SelectList no ASP.net MVC

112

Basicamente, estou tentando inserir um item no início de uma SelectList com o valor padrão de 0 e o valor de texto de "- Selecione um -"

Algo como

SelectList list = new SelectList(repository.func.ToList());
ListItem li = new ListItem(value, value);
list.items.add(li);

Isso pode ser feito?

GEOCHET
fonte
2
SelectListrealmente parece ser apenas um auxiliar para vincular dados diretamente a itens. Se você adicionar itens manualmente, use List<SelectListItem>.
Kai Hartmann
Considerando a resposta aceita e o número de votos, posso sugerir que você altere ligeiramente a pergunta para refletir essa resposta i, e, "Como posso adicionar um item de valor em branco a uma SelectList no ASP.net MVC"? Mas crédito e obrigado a @ h-dog por responder à pergunta original "Como posso adicionar um item" per se
AndrewD

Respostas:

150

Realmente não há necessidade de fazer isso a menos que você insista no valor de 0. A extensão HtmlHelper DropDownList permite que você defina um rótulo de opção que aparece como o valor inicial no select com um valor nulo. Basta usar uma das assinaturas DropDownList que possui o rótulo de opção.

<%= Html.DropDownList( "DropDownValue",
                       (IEnumerable<SelectListItem>)ViewData["Menu"],
                        "-- Select One --" ) %>
Tvanfosson
fonte
1
E se você realmente insistir no valor 0? Se o valor for nulo / uma string vazia, isso pode causar problemas com a vinculação do modelo.
Kjensen
2
Se você está esperando de volta como um int, eu usaria int? e ainda deixá-lo nulo se nenhuma seleção foi feita.
tvanfosson
13
O problema com esta solução é que você perde o item selecionado.
37Stars
1
@JesseWebb Suspeito que você só precisa se certificar de que está usando uma assinatura que inclui o rótulo de opção, msdn.microsoft.com/en-us/library/ee703567.aspx , @Html.DropDownListFor( m => m.MenuSelection, (IEnumerable<SelectListItem>)ViewBag.Menu, "Select One", null )por exemplo, incluindo o nulo htmlAttributespara evitar confusão com a assinatura que leva uma expressão, a enumeração de menu e um objeto (htmlAttributes).
tvanfosson
1
@tvanfosson - Obrigado por esclarecer. Tentei usá-lo com um tipo Complex como o tipo para o IEnumerable na SelectList. Eu tive que especificar o dataValueFielde o dataTestFieldque fez isso não funcionar ao adicionar um valor de optionLabel. Provavelmente poderia ter funcionado com um pouco mais de esforço, mas acabei de usar uma das soluções alternativas. Mesmo assim, obrigado!
Jesse Webb
82

Eu fiz isso funcionar preenchendo um SelectListItem, convertendo em uma lista e adicionando um valor no índice 0.

List<SelectListItem> items = new SelectList(CurrentViewSetups, "SetupId", "SetupName", setupid).ToList(); 
items.Insert(0, (new SelectListItem { Text = "[None]", Value = "0" }));
ViewData["SetupsSelectList"] = items;
davewilliams459
fonte
Eu recomendo usar a opção de sobrecarga de rótulo no HtmlHelper -> @ Html.DropDownListFor
2b77bee6-5445-4c77-b1eb-4df3e5
17

Isso é possível.

//Create the select list item you want to add
SelectListItem selListItem = new SelectListItem() { Value = "null", Text = "Select One" };

//Create a list of select list items - this will be returned as your select list
List<SelectListItem> newList = new List<SelectListItem>();

//Add select list item to list of selectlistitems
newList.Add(selListItem);

//Return the list of selectlistitems as a selectlist
return new SelectList(newList, "Value", "Text", null);
eaf
fonte
Eu recomendo usar a opção de sobrecarga de rótulo no HtmlHelper -> @ Html.DropDownListFor
2b77bee6-5445-4c77-b1eb-4df3e5
13

Gostei da resposta de @AshOoO, mas como @Rajan Rawal, eu precisava preservar o estado do item selecionado, se houver. Então eu adicionei minha customização ao seu métodoAddFirstItem()

public static SelectList AddFirstItem(SelectList origList, SelectListItem firstItem)
{
    List<SelectListItem> newList = origList.ToList();
    newList.Insert(0, firstItem);

    var selectedItem = newList.FirstOrDefault(item => item.Selected);
    var selectedItemValue = String.Empty;
    if (selectedItem != null)
    {
        selectedItemValue = selectedItem.Value;
    }

    return new SelectList(newList, "Value", "Text", selectedItemValue);
}
H Dog
fonte
Eu recomendo usar a opção de sobrecarga de rótulo no HtmlHelper -> @ Html.DropDownListFor
2b77bee6-5445-4c77-b1eb-4df3e5
5
private SelectList AddFirstItem(SelectList list)
        {
            List<SelectListItem> _list = list.ToList();
            _list.Insert(0, new SelectListItem() { Value = "-1", Text = "This Is First Item" });
            return new SelectList((IEnumerable<SelectListItem>)_list, "Value", "Text");
        }

Isso deve fazer o que você precisa, basta enviar sua lista de seleção e ela retornará uma lista de seleção com um item no índice 0

Você pode custear o texto, valor ou mesmo o índice do item que você precisa inserir

AshOoO
fonte
e se eu tiver alguns valores selecionados e quiser preservá-los?
Rajan Rawal
Eu recomendo usar a opção de sobrecarga de rótulo no HtmlHelper -> @ Html.DropDownListFor
2b77bee6-5445-4c77-b1eb-4df3e5
5

Aqui ajudante html para você

public static SelectList IndividualNamesOrAll(this SelectList Object)
{
    MedicalVarianceViewsDataContext LinqCtx = new MedicalVarianceViewsDataContext();

    //not correct need individual view!
    var IndividualsListBoxRaw =  ( from x in LinqCtx.ViewIndividualsNames 
                                 orderby x.FullName
                                 select x);

    List<SelectListItem> items = new SelectList (
                               IndividualsListBoxRaw, 
                              "First_Hospital_Case_Nbr", 
                              "FullName"
                               ).ToList();

    items.Insert(0, (new SelectListItem { Text = "All Individuals", 
                                        Value = "0.0", 
                                        Selected = true }));

    Object = new SelectList (items,"Value","Text");

    return Object;
}
escondido
fonte
3

O método .ToList (). Insert (..) coloca um elemento em sua lista. Qualquer posição pode ser especificada. Depois de ToList, basta adicionar .Insert (0, "- - Primeiro Item - -")

Seu código

SelectList list = new SelectList(repository.func.ToList());
ListItem li = new ListItem(value, value);
list.items.add(li);

Novo Código

SelectList list = new SelectList(repository.func.ToList().Insert(0, "- - First Item - -"));
ListItem li = new ListItem(value, value);
list.items.add(li);
Moji
fonte
2

Pode não parecer muito elegante, mas geralmente faço algo assim:

    var items = repository.func.ToList();
    items.Insert(0, new funcItem { ID = 0, TextValue = "[None]" });
    ViewBag.MyData = new SelectList(items);
Androiderson
fonte
1

Ok, eu gosto de código limpo, então fiz disso um método de extensão

static public class SelectListHelper
{
    static public SelectList Add(this SelectList list, string text, string value = "", ListPosition listPosition = ListPosition.First)
    {
        if (string.IsNullOrEmpty(value))
        {
            value = text;
        }
        var listItems = list.ToList();
        var lp = (int)listPosition;
        switch (lp)
        {
            case -1:
                lp = list.Count();
                break;
            case -2:
                lp = list.Count() / 2;
                break;
            case -3:
                var random = new Random();
                lp = random.Next(0, list.Count());
                break;
        }
        listItems.Insert(lp, new SelectListItem { Value = value, Text = text });
        list = new SelectList(listItems, "Value", "Text");
        return list;
    }

    public enum ListPosition
    {
        First = 0,
        Last = -1,
        Middle = -2,
        Random = -3
    }
}

Uso (por exemplo):

var model = new VmRoutePicker
    {
     Routes =
     new SelectList(_dataSource.Routes.Select(r => r.RouteID).Distinct())
     };                                     
  model.Routes = model.Routes.Add("All", "All", SelectListHelper.ListPosition.Random);
//or
  model.Routes = model.Routes.Add("All");
Jeff
fonte
1

Como esta opção pode necessitar de muitas maneiras diferentes, cheguei à conclusão de desenvolver um objeto para que possa ser utilizado em diferentes cenários e em projetos futuros

primeiro adicione esta classe ao seu projeto

public class SelectListDefaults
{
    private IList<SelectListItem> getDefaultItems = new List<SelectListItem>();

    public SelectListDefaults()
    {
        this.AddDefaultItem("(All)", "-1");
    }
    public SelectListDefaults(string text, string value)
    {
        this.AddDefaultItem(text, value);
    }
    public IList<SelectListItem> GetDefaultItems
    {
        get
        {                
            return getDefaultItems;
        }

    }
    public void AddDefaultItem(string text, string value)
    {        
        getDefaultItems.Add(new SelectListItem() { Text = text, Value = value });                    
    }
}

Agora, em Controller Action, você pode fazer assim

    // Now you can do like this
    ViewBag.MainCategories = new SelectListDefaults().GetDefaultItems.Concat(new SelectList(db.MainCategories, "MainCategoryID", "Name", Request["DropDownListMainCategory"] ?? "-1"));
    // Or can change it by such a simple way
    ViewBag.MainCategories = new SelectListDefaults("Any","0").GetDefaultItems.Concat(new SelectList(db.MainCategories, "MainCategoryID", "Name", Request["DropDownListMainCategory"] ?? "0"));
    // And even can add more options
    SelectListDefaults listDefaults = new SelectListDefaults();
    listDefaults.AddDefaultItme("(Top 5)", "-5");
    // If Top 5 selected by user, you may need to do something here with db.MainCategories, or pass in parameter to method 
    ViewBag.MainCategories = listDefaults.GetDefaultItems.Concat(new SelectList(db.MainCategories, "MainCategoryID", "Name", Request["DropDownListMainCategory"] ?? "-1"));

E, finalmente, em View, você codificará assim.

@Html.DropDownList("DropDownListMainCategory", (IEnumerable<SelectListItem>)ViewBag.MainCategories, new { @class = "form-control", onchange = "this.form.submit();" })
sairfan
fonte
0

Uma solução alternativa é usar a resposta de @tvanfosson (a resposta selecionada) e usar JQuery (ou Javascript) para definir o valor da opção como 0:

$(document).ready(function () {
        $('#DropDownListId option:first').val('0');
    });

Espero que isto ajude.

cara lógico
fonte
0

Tente algo como o seguinte código:

MyDAO MyDAO = new MyDAO();    
List<MyViewModel> _MyDefault = new List<MyViewModel>() {
                new MyViewModel{
                    Prop1= "All",
                    Prop2 = "Select all"
                }
            };
            ViewBag.MyViewBag= 
                new SelectList(MyDAO
                .MyList().Union(
                    _MyDefault
                    ), "Prop1", "Prop2");
Enrique Mingyar Torrez Hinojos
fonte
-5

Eu não sei se alguém tiver uma opção melhor ...

<% if (Model.VariableName == "" || Model.VariableName== null) { %>
   <%= html.DropDpwnList("ListName", ((SelectList) ViewData["viewName"], "", 
        new{stlye=" "})%>
<% } else{ %>
<%= html.DropDpwnList("ListName", ((SelectList) ViewData["viewName"], 
        Model.VariableName, new{stlye=" "})%>
<% }>
New2this
fonte