2012-03-20 9 views
6

Mam problemy podczas wybierania wartości DropDownList. Czytałem wszystkie podobne posty i nie mogę znaleźć rozwiązania.Wybrana właściwość w SelectListItem nigdy nie działa (DropDownListFor)

Faktyczne podejście wydaje się bardzo dobry dla mnie, bo mogę sprawdzać pola, które będą wewnątrz selectList:

var selectList = new List<SelectListItem>(
    from variable in someKindOfCollection 
    select new SelectListItem 
     { 
      Selected = variable.Property == selection, 
      Text = variable.Property, 
      Value = variable.Property 
     }); 

Podobno to daje mi całkowitą kontrolę. Po utworzeniu listy selectList mogę sprawdzać zmienne za pomocą debuggera. Wszystko jest w porządku, a jeden z nich ma zaznaczony atrybut "Wybrany".

Następnie używam DropDownListFor aby pokazać na widoku:

@Html.DropDownListFor(
    g => g.SomePropertyInModel , selectList, new { @class = "cssClass" }) 

Ale to nie działa, nigdy ... „Renders” listę rozwijaną, ale nic nie jest zaznaczone.

Thanks a lot :)

NEW Przykład Przede wszystkim chcę przeprosić. Ukrywałem informacje, oczywiście zupełnie nieumyślnie. Cały kod dzieje wewnątrz pętli for Razor:

@foreach (var loopVariable in Model.Collection) 
{ 
    if (Model.SomeCondition != null) 
    { 
     selection = someValue; 
    } 

    var selectList = new List<SelectListItem>(
     from variable in someKindOfCollection 
     select new SelectListItem 
    { 
     Selected = variable.Property == selection, 
     Text = variable.Property, 
     Value = variable.Property 
    }); 

    @Html.DropDownListFor(
     g => g.SomePropertyInModel , selectList, new { @class = "cssClass" }) 

} 

Tak, to fakt selectList jest zmienna lokalna przyczyną problemu ?. Przepraszam, nie myślałem, że to jest to.

+1

Czy możesz dołączyć wyjście HTML rozwijanego menu? – Brandon

+0

Dzięki Brandon, zaktualizowałem post. – IoChaos

Odpowiedz

2

Polecam korzystanie z modelu Widok:

public ActionResult Index() 
{ 
    var model = new MyViewModel 
    { 
     // this will preselect the item with value = "2.400 €" in the collection 
     SelectedValue = "2.400 €", 

     Values = someKindOfCollection 
    }; 
    return View(model); 
} 

oraz w widoku:

@Html.DropDownListFor(
    g => g.SelectedValue, 
    new SelectList(Model.Values, "SomePropertyForValue", "SomePropertyForText"), 
    new { @class = "cssClass" } 
) 
+0

Cześć Darin i dziękuję za poświęcony czas. Nie rozumiem, gdzie twój przykład różni się od mojego. Widzę, że używasz SelectList (której użyłem bez szczęścia). Moja kolekcja i wybrane pole również pochodzi z viewModel. – IoChaos

+0

@IoChaos, nie wiem. Od Ciebie zależy, jak to się zmieni. Ponieważ moje działa.Przetestowałem to. –

+0

Przepraszam, Darin :(... proszę, zobacz moją ostatnią aktualizację – IoChaos

2

ponownie Należy debugowania listy select.

Żadna z wartości opcji nie ma wartości selected=selected.

Spróbuj ciężko kodowania listy do czegoś jak

SelectList = new List<SelectListItem> 
     { 
      new SelectListItem{Text = "600 €", Value="600 €" , Selected = false}, 
      new SelectListItem{Text = "1.200 €", Value="1.200 €" , Selected = false}, 
      new SelectListItem{Text = "2.400 €", Value="2.400 €" , Selected = false}, 
      new SelectListItem{Text = "3.000 €", Value="3.000 €" , Selected = true}, 
     }; 

Używając tego kodu, a Html.DropDownFor SelectList działa poprawnie i generuje ten kod HTML

<select id="TheID" name="TheName" class="cssClass"> 
    <option value="600 €">600 €</option> 
    <option value="1.200 €">1.200 €</option> 
    <option value="2.400 €">2.400 €</option> 
    <option value="3.000 €" selected="selected">3.000 €</option> 
</select> 

ze swojego kodu, nie mogę powiedzieć jeśli porównanie polega na ustawieniu jednego z wybranych atrybutów na prawdziwy, ale prawdopodobnie dlatego Twój kod nie działa.

+0

Dzięki Brandon Naprawiłem kolekcję i to nie działa, ale coś odkryłem Kiedy generuję kolekcję jeden z elementów jest z Selected = true.Po linii, która zawiera "DropDownListFor" wszystkie atrybuty są fałszywe Czy to normalne? – IoChaos

+1

@IoChaos, nie o tym wiem, może to pomogłoby gdybyś mógł opublikować cały powtarzalny przykład Mówisz, że ciągniesz właściwości z ViewMod el, ale z twojej deklaracji 'selectList' wygląda na to, że deklarujesz zmienną lokalną. Może potrzebujemy zobaczyć cały kod, którego używasz, ponieważ to, co napisaliśmy wspólnie z Darinem, powinno działać. – Brandon

+0

Przykro nam Brandon :(, proszę, zobacz moją ostatnią aktualizację. – IoChaos

4

Myślę, że masz ten sam problem co ja. Przejrzałem kod źródłowy, aby znaleźć moje rozwiązanie i wydaje mi się, że jest to błąd. Poniższy DropDownListFor powinien pomóc, kluczem do tego jest przekazanie wybranej wartości do helpera HTML. Mam nadzieję że to pomoże.

public static class SelectExtensions { 
    public static IHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList, string selectedValue, string optionLabel, object htmlAttributes = null) { 
     return DropDownListHelper(helper, ExpressionHelper.GetExpressionText(expression), selectList, selectedValue, optionLabel, htmlAttributes); 
    } 

    /// <summary> 
    /// This is almost identical to the one in ASP.NET MVC 3 however it removes the default values stuff so that the Selected property of the SelectListItem class actually works 
    /// </summary> 
    private static IHtmlString DropDownListHelper(HtmlHelper helper, string name, IEnumerable<SelectListItem> selectList, string selectedValue, string optionLabel, object htmlAttributes) { 
     name = helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name); 

     // Convert each ListItem to an option tag 
     var listItemBuilder = new StringBuilder(); 

     // Make optionLabel the first item that gets rendered 
     if (optionLabel != null) 
      listItemBuilder.AppendLine(ListItemToOption(new SelectListItem() { Text = optionLabel, Value = String.Empty, Selected = false }, selectedValue)); 

     // Add the other options 
     foreach (var item in selectList) { 
      listItemBuilder.AppendLine(ListItemToOption(item, selectedValue)); 
     } 

     // Now add the select tag 
     var tag = new TagBuilder("select") { InnerHtml = listItemBuilder.ToString() }; 
     tag.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); 
     tag.MergeAttribute("name", name, true); 
     tag.GenerateId(name); 

     // If there are any errors for a named field, we add the css attribute 
     ModelState modelState; 

     if (helper.ViewData.ModelState.TryGetValue(name, out modelState)) { 
      if (modelState.Errors.Count > 0) 
       tag.AddCssClass(HtmlHelper.ValidationInputCssClassName); 
     } 

     // Add the unobtrusive validation attributes 
     tag.MergeAttributes(helper.GetUnobtrusiveValidationAttributes(name)); 

     return tag.ToHtmlString(TagRenderMode.Normal); 
    } 

    private static string ListItemToOption(SelectListItem item, string selectedValue) { 
     var tag = new TagBuilder("option") { InnerHtml = HttpUtility.HtmlEncode(item.Text) }; 

     if (item.Value != null) 
      tag.Attributes["value"] = item.Value; 

     if ((!string.IsNullOrEmpty(selectedValue) && item.Value == selectedValue) || item.Selected) 
      tag.Attributes["selected"] = "selected"; 

     return tag.ToString(TagRenderMode.Normal); 
    } 
} 
+0

Właśnie zaktualizowałem to z poprawką, aby upewnić się, że atrybuty danych HTML 5 działają, gdy są podawane za pomocą anonimowego obiektu. – nfplee

1

miałem podobny problem, a przyczyną było to, że nie było ustawienie wartości dla właściwości w moim modelu widoku, który był wchłaniany przez SelectListItems. W rzeczywistości nie musisz w ogóle ustawiać właściwości "Wybrane". Aby użyć tekstu z oryginalnego przykładu, po prostu ustaw "SomePropertyOnModel" na dowolne obecne zaznaczenie. DropDownListFor odpowiednio powiąza właściwość "Wybrane".

2

Nie wiem, czy to pomoże nikomu, ale to rozwiązać to dla mnie ....

miałem zarówno gromadzenie i wybraną wartość w moim modelu.

zmieniłem pogląd od:

@Html.DropDownListFor(
g => g.CollectionName, 
new SelectList(Model.CollectionName, "SomePropertyForValue", "SomePropertyForText", Model.SelectedValue), 
new { @class = "cssClass" } 
) 

do

@Html.DropDownListFor(
g => g.SelectedValue, 
new SelectList(Model.CollectionName, "SomePropertyForValue", "SomePropertyForText", Model.SelectedValue), 
new { @class = "cssClass" } 
) 

Kiedy mój pierwszy parametr do DropDownListFor odwołuje kolekcję, chciałbym uzyskać listy rozwijanej ale wybrana wartość nigdy nie będzie trzymać .

-1

Wystąpił problem, g.SelectedValue musi być typem zerowym w modelu.

2

Rozwiązaniem tego problemu jest prostsze, że wszyscy myślą ...

Wszystko, co musimy zrobić, gdy powrót widok z kontrolera jest ustawiona właściwość modelu widoku dla elementu że rozwijana jest zobowiązany do - to znaczy: model.SomePropertyInModel = '5' na przykład

ten sposób, gdy robimy to

@Html.DropDownListFor(
g => g.SomePropertyInModel , selectList, new { @class = "cssClass" }) 

HtmlHelper automatycznie podnieść wartość domyślną, aby wyświetlić na DropDownList

simples!

Mam nadzieję, że może pomóc Tobie i wszystkim innym - takim jak ja! - które straciły dużo czasu szukając rozwiązania dla tego oczywistego problemu.

0

Moja rekomendacja dla DropDownListFor jest

  • mają właściwość IEnumerable modelu (lub ViewModel), który jest przekazywany do widoku. W twoim przypadku, na przykład:

    private IEnumerable<SelectListItem> GetListItems() 
    { 
        var selectList = db.YourDBThings 
         .Where(t => t.IsCool == true) 
         .Select(x => new SelectListItem 
          { 
          Value = x.Id.ToString(), 
          Text = x.Name 
          }); 
        return new SelectList(issues, "Value", "Text"); 
    } 
    
  • a następnie dodać ten IEnumerable do obiektu, przy założeniu, że również mają właściwość w swoim obiekcie, który ma jeden element (ten, który zostanie ustawiony jako wybrany), który odpowiada jednemu z „wartość” w liście:

    FancyViewModel myFancyViewModel = new FancyViewModel(); 
    myFancyViewModel.ListOptions = GetListItems(); 
    myFancyViewModel.SelectedThingId = 3; //this 3 would match one of the value in the list 
    //.... 
    return View(myFancyViewModel); 
    
  • Następnie w widoku, w którym otrzymują instancję FancyViewModel zawierający listę elementów:

    @model Project.ViewModels.FancyViewModel 
    @*...*@ 
    @Html.DropDownListFor(x=>x.SelectedThingId, Model.ListOptions) 
    

Pierwszy argument w polu DropDownListFor określa właściwość TProperty, która zawiera pole, które zostanie wybrane na liście. Druga to sama lista, która pochodzi z modelu (choć można ją pobrać z dowolnego miejsca!).

Powiązane problemy