2010-03-09 17 views
26

Zauważyłem, co wydaje mi się błąd w asp.net MVC lub po prostu robię coś nie tak. Obecnie używam 1.0, więc może to jest coś, co zostanie omówione w wydaniu 2.0. Ale tak czy inaczej, zaczynamy.DropDownList ustawienie wybranego elementu w asp.net MVC

Gdy mój model widoku ma właściwość, która ma taką samą nazwę, jak deklarowany identyfikator dla rozwijanej listy, wybrany element jest ignorowany, a renderowany HTML nie zawiera niczego. Nie jestem pewien, czy coś zrobiłem źle, ale zmiana nazwy identyfikatora rozwiązuje problem. Uprośniłem przykład, mam nadzieję, że jest jasne, w przeciwnym razie proszę dać mi znać.

Oto mój widok gdzie deklarowana ID jest taka sama jak nazwa mojej liście w modelu:

<table border="0" cellpadding="0" cellspacing="0"> 
    <tr> 
     <td> 
     <%= Html.DropDownList("IsMultipleServicers", Model.IsMultipleServicers) %> 
     </td> 
    </tr> 
</table> 

a renderowane HTML

<table border="0" cellpadding="0" cellspacing="0"> 
     <tr> 
     <td> 
      <select id="IsMultipleServicers" name="IsMultipleServicers"> 
       <option value="false">No</option> 
       <option value="true">Yes</option> 
      </select> 
     </td> 
     </tr> 
</table> 

Teraz pozwala zrobić mała zmiana. Zmienię zadeklarowany identyfikator na coś innego.

Oto moim zdaniem:

<table border="0" cellpadding="0" cellspacing="0"> 
    <tr> 
     <td> 
      <%= Html.DropDownList("MultipleServicers", Model.IsMultipleServicers) %> 
     </td> 
    </tr> 
</table> 

A teraz wytopione html:

<table border="0" cellpadding="0" cellspacing="0"> 
    <tr> 
     <td> 
     <select id="IsMultipleServicers" name="IsMultipleServicers"> 
      <option value="false">No</option> 
      <option selected="selected" value="true">Yes</option> 
     </select> 
     </td> 
    </tr> 
</table> 

Zauważ, że teraz mam wybraną opcję, który byłby drugi element na liście.

Oto moje ViewModel prostu związać wszystko razem:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.Mvc; 

namespace MVCProject.Models.ViewModels.Service 
{ 
    public class ServiceViewModel : ViewModel 
    { 
     public List<SelectListItem> IsMultipleServicers { get; set; } 
    } 
} 

Oto moje działanie:

[AcceptVerbs(HttpVerbs.Get)] 
public virtual ActionResult Service() 
{ 
    return View(new ServiceViewModel() 
    { 
     IsMultipleServicers = BuildBooleanSelectList(true) 
    }; 
} 

private List<SelectListItem> BuildBooleanSelectList(bool isTrue) 
{ 
    List<SelectListItem> list = new List<SelectListItem>(); 

    if (isTrue) 
    { 
     list.Add(new SelectListItem() { Selected = false, Text = "No", Value = "false" }); 
     list.Add(new SelectListItem() { Selected = true, Text = "Yes", Value = "true" }); 
    } 
    else 
    { 
     list.Add(new SelectListItem() { Selected = true, Text = "No", Value = "false" }); 
     list.Add(new SelectListItem() { Selected = false, Text = "Yes", Value = "true" }); 
    } 
return list; 
    } 

Odpowiedz

43

Myślę, że problemem jest zamieszanie dotyczące DropDownList przeciążeń:

  1. Html.DropDownList(string name) szuka właściwości modelu widoku name i typu IEnumerable<SelectListItem>. Będzie używać wybranego elementu (SelectListItem.Selected == true) z listy, chyba że istnieje wartość postu formularza o tej samej nazwie.

  2. używa elementów z selectList, ale nie ich wybranych wartości. Wybrany element zostaje znaleziony przez przekształcenie name w modelu widoku (lub danych post) i dopasowanie go do SelectListItem.Value. Nawet jeśli nie można znaleźć wartości (lub ma wartość NULL), nadal nie będzie używać wybranej wartości z listy SelectListItems.

Twój kod wykorzystuje drugie przeciążenie, ale określa właściwość "value", która nie istnieje ("MultipleServicers").

Aby rozwiązać problem, należy użyć pierwszego przeciążeniem:

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

Lub dodać obiekt string MultipleServicers do widoku modelu i wypełnić go w kontrolerze. Polecam takie rozwiązanie, jak robi się wokół kilku problemów z początkowym wyświetlacz, postu i mapowania danych post do modelu view/post:

public class ServiceViewModel : ViewModel 
{ 
    public string MultipleServicers { get; set; } 
    public List<SelectListItem> IsMultipleServicers { get; set; } 
} 

Następnie dla HTML:

<%= Html.DropDownList(Model.MultipleServicers, Model.IsMultipleServicers) %> 

ten technika mapuje również na MVC2:

<%= Html.DropDownListFor(x => x.MultipleServicers, Model.IsMultipleServicers) %> 
+0

Chciałbym, żeby było to bardziej oczywiste ... Ale teraz ma sens. Dzięki – ppumkin

+0

polecam wszystkim: http://www.c-sharpcorner.com/UploadFile/4d9083/creating-simple-cascading-dropdownlist-in-mvc-4-using-razor/ – Umitk

2

Pomocnik DropDownList pobiera domyślną wartość z modelu. W pierwszym przypadku wartość w modelu odpowiadającym nazwie to SelectList - nie pasuje ona do żadnej z pozycji na liście, jest to lista, więc nie wybrano żadnej wartości. W drugim przykładzie twój model nie zawiera właściwości o tej nazwie, więc nie można użyć wartości z modelu i domyślnie jest to stan wskazany w samej liście SelectList. Zazwyczaj będę miał właściwość w modelu dla wybranej wartości - stanie się to domyślną - i inną właściwość reprezentującą potencjalne wartości dla listy.

+0

Dobre wyjaśnienie tego, co jest wydarzenie! Osadzony na domyślnej praktyce - wydaje się najlepszym sposobem na wyraźne przedstawienie i upraszcza generowanie wartości SelectListItem. –

9

Napotkano ten sam problem przy użyciu przeciążenia Html.DropDownList (string name, IEnumerable selectList). Wygląda na to, że mój model ma właściwość o tej samej nazwie co nazwa rozwijanej listy. W tym przypadku MVC faworyzował wartość właściwości mojego Modelu względem właściwości Selected każdego wpisu w IEnumerable.

Rozwiązaniem było użycie nazwy listy rozwijanej, która nie pasuje do nazwy właściwości. Innym rozwiązaniem byłoby napisanie własnej metody rozszerzenia, która ignoruje model i stan widoku, a zamiast tego zawsze honoruje wybraną właściwość.

+1

Musiałem użyć tego podejścia wcześniej dla szybkich poprawek, ale myślę, że dobrze jest wrócić później i refaktoryzować swoje modele widoków, aby lepiej wykorzystać Html.DropDownList, jak to miało być użyte (jako mylące, ponieważ może dostać) –

Powiązane problemy