ASP.NET MVC Html.DropDownList SelectedValue


103

Bunu denedim RC1 ve ardından sorunu çözmeyen RC2'ye yükselttim.

// in my controller
ViewData["UserId"] = new SelectList(
    users, 
    "UserId", 
    "DisplayName", 
    selectedUserId.Value); // this has a value

sonuç: SelectedValue özelliği nesnede ayarlanır

// in my view
<%=Html.DropDownList("UserId", (SelectList)ViewData["UserId"])%>

sonuç: tüm beklenen seçenekler istemciye işlenir, ancak seçilen öznitelik ayarlanmamıştır. SelectedValue'daki öğe listede bulunur, ancak listedeki ilk öğe her zaman varsayılan olarak seçilidir.

Bunu nasıl yapmalıyım?

Güncelleme John Feminella'nın cevabı sayesinde sorunun ne olduğunu öğrendim. "UserId", Modelde Görünümümün kesinlikle yazıldığı bir özelliktir. Html.DropDownList ("UserId", "UserId" dışında herhangi bir adla değiştirildiğinde, seçilen değer doğru şekilde oluşturulur.

Bu, değerin modele bağlı olmamasına neden olur.


Değerin listede olduğundan emin misiniz?
John Sheehan

Sorun hala ASP.NET MVC
Mathias F'nin 1.

SelectedUserId nedir !?
fulvio

Girişinizin adı mülkünüzle aynı değilse, güncellemedeki değeri nasıl bağlamayı düşünüyorsunuz?
ryudice

Yanıtlar:


68

Bu sorunu şu şekilde çözdüm:

Aşağıdakilere sahiptim:

Denetleyici:

ViewData["DealerTypes"] = Helper.SetSelectedValue(listOfValues, selectedValue) ;

Görünüm

<%=Html.DropDownList("DealerTypes", ViewData["DealerTypes"] as SelectList)%>

Aşağıdakiler tarafından değiştirildi:

Görünüm

<%=Html.DropDownList("DealerTypesDD", ViewData["DealerTypes"] as SelectList)%>

DropDown'ın aynı ada sahip olmaması gerektiği anlaşılıyor: ViewData adı: S garip ama işe yaradı.


19
"DropDown için +1 aynı ada sahip olmamalıdır" ViewData adı "Büyük Teşekkürler
Daniel Dyson

Teşekkür ederim!!! Bu :) neden işe yaramadığını sadece merak birçok saat sonra benim sorun çözüldü
Jen

1
Bu seçilen değer için işe yarar, ancak DropDownList artık modelde bulunmayan "DealerTypesDD" ye bağlı olduğundan, veritabanındaki "DealerTypes" i güncellemeye çalıştığınızda bir sorun ortaya çıkar. Geçici bir çözüm, DropDownList'e gizli bir alan ve htmlAttributes eklemektir: <input type = "hidden" name = "DealerTypes" id = "DealerTypes" value = "" /> <% = Html.DropDownList ("DealerTypesDD", ViewData [ "DealerTypes"] SelectList olarak, yeni {@onchange = "DealerTypes.value = this.value"})%>
Zim


1
Ne oluyor be! Bu MVC5'te düzeltilmedi ??? @Paul Hatcher tarafından bahsedilen başka bir numara olarak, seçilen kimliği ViewData ["DealerTypes"] içine kopyalayın.
jsgoupil

51

Bunu dene:

public class Person {
    public int Id { get; set; }
    public string Name { get; set; }
}

Ve sonra:

var list = new[] {   
    new Person { Id = 1, Name = "Name1" }, 
    new Person { Id = 2, Name = "Name2" }, 
    new Person { Id = 3, Name = "Name3" } 
};

var selectList = new SelectList(list, "Id", "Name", 2);
ViewData["People"] = selectList;

Html.DropDownList("PeopleClass", (SelectList)ViewData["People"])

MVC RC2 ile şunları elde ederim:

<select id="PeopleClass" name="PeopleClass">
    <option value="1">Name1</option>
    <option selected="selected" value="2">Name2</option>
    <option value="3">Name3</option>
</select>

Bu, nedeni bulmada yardımcı oldu. Eklemeleri yansıtmak için sorumu güncelledim.
blu

modelde ilk mi? denetleyicide ikinci mi? ve üçüncüsü net, ama 2 birinci .. ???
rr

Güzel yanıt, ancak bir ViewModel kullanmak daha iyi değil mi?
Jess

@Jess: Bu cevabı 5 yıl önce Mart 2009'da yazdım. Zaman değişti! Güncellemekten çekinmeyin. :)
John Feminella

5

DropDown'u hala "UserId" olarak adlandırabilir ve model bağlamanın sizin için doğru şekilde çalışmasını sağlayabilirsiniz.

Bunun çalışması için tek gereksinim, SelectList'i içeren ViewData anahtarının, bağlamak istediğiniz Model özelliği ile aynı ada sahip olmamasıdır. Özel durumunuzda bu şöyle olacaktır:

// in my controller
ViewData["Users"] = new SelectList(
    users, 
    "UserId", 
    "DisplayName", 
    selectedUserId.Value); // this has a value

// in my view
<%=Html.DropDownList("UserId", (SelectList)ViewData["Users"])%>

Bu, UserId adlı, modelinizdeki UserId özelliğiyle aynı ada sahip bir seçme öğesi oluşturur ve bu nedenle model bağlayıcı, Html.DropDownList yardımcısı tarafından oluşturulan html'nin seçme öğesinde seçilen değerle ayarlayacaktır.

Seçme listesini ViewData'ya özellik adına eşit bir anahtarla koyduğunuzda, belirli Html.DropDownList yapıcısının SelectList'te belirtilen değeri neden seçmediğinden emin değilim. Bunun, DropDownList yardımcısının diğer senaryolarda nasıl kullanıldığı ile bir ilgisi olduğundan şüpheleniyorum, burada kural, ViewData'da modelinizdeki özellik ile aynı ada sahip bir SelectList'e sahip olmanızdır. Bu doğru çalışacak:

// in my controller
ViewData["UserId"] = new SelectList(
    users, 
    "UserId", 
    "DisplayName", 
    selectedUserId.Value); // this has a value

// in my view
<%=Html.DropDownList("UserId")%>

Çok teşekkürler dostum, her şeyden önce bu benim için çalıştı, nedenini bilmiyorum ama işe yaradı
Lamin Sanneh

En sonunda! Saatler süren denemelerden sonra nihayet "tek ihtiyacınızı" buldum. Başardı.
SteveCav

2

Bunun ekibin düzeltmesi gereken bir hata olduğunu düşünmezsek, MSDN'nin belgeyi iyileştirmesi gerekir. Kafa karıştırıcı, gerçekten bunun zayıf belgesinden geliyor. Gelen MSDN , bu parametreler açıklıyor adını gibi

Type: System.String
The name of the form field to return.

Bu sadece ürettiği son html'nin bu parametreyi select girdisinin adı olarak kullanacağı anlamına gelir. Ama aslında bundan daha fazlasını ifade ediyor.

Sanırım tasarımcı, kullanıcının açılır listeyi görüntülemek için bir görünüm modeli kullanacağını ve aynı görünüm modeline geri göndermeyi kullanacağını varsayıyor . Ancak çoğu durumda, bu varsayımı gerçekten takip etmiyoruz.

Yukarıdaki örneği kullanın,

public class Person {
    public int Id { get; set; }
    public string Name { get; set; }
}

Varsayımı takip edersek, bu açılır liste ile ilgili görünüm için bir görünüm modeli tanımlamalıyız.

public class PersonsSelectViewModel{
    public string SelectedPersonId,
    public List<SelectListItem> Persons;
}

Geri gönderirken, yalnızca seçilen değer geri gönderilecektir, bu nedenle modelin SelectedPersonId özelliğine geri gönderilmesi gerektiğini varsayar, bu da Html.DropDownList'in ilk parametre adının 'SelectedPersonId' olması gerektiği anlamına gelir . Bu nedenle tasarımcı, model görünümünü görünümde görüntülerken, modelin SelectedPersonId özelliğinin bu açılır listenin varsayılan değerini tutması gerektiğini düşünür. List <SelectListItem> Persons'ünüzün Selected bayrağını, hangisinin seçili / varsayılan olduğunu belirtmek için zaten ayarladığı düşünülse bile, tml.DropDownList aslında bunu yok sayacak ve kendi IEnumerable <SelectListItem> adını yeniden oluşturacak ve varsayılan / seçilen öğeyi ada göre ayarlayacaktır.

İşte asp.net mvc kodudur

private static MvcHtmlString SelectInternal(this HtmlHelper htmlHelper, ModelMetadata metadata,
            string optionLabel, string name, IEnumerable<SelectListItem> selectList, bool allowMultiple,
            IDictionary<string, object> htmlAttributes)
{
    ...

    bool usedViewData = false;

    // If we got a null selectList, try to use ViewData to get the list of items.
    if (selectList == null)
    {
        selectList = htmlHelper.GetSelectData(name);
        usedViewData = true;
    }

    object defaultValue = (allowMultiple) ? htmlHelper.GetModelStateValue(fullName, typeof(string[])) : htmlHelper.GetModelStateValue(fullName, typeof(string));

    // If we haven't already used ViewData to get the entire list of items then we need to
    // use the ViewData-supplied value before using the parameter-supplied value.
    if (defaultValue == null && !String.IsNullOrEmpty(name))
    {
        if (!usedViewData)
        {
            defaultValue = htmlHelper.ViewData.Eval(name);
        }
        else if (metadata != null)
        {
            defaultValue = metadata.Model;
        }
    }

    if (defaultValue != null)
    {
        selectList = GetSelectListWithDefaultValue(selectList, defaultValue, allowMultiple);
    }

    ...

    return tagBuilder.ToMvcHtmlString(TagRenderMode.Normal);
}

Böylece, kod aslında daha da ileri gitti, sadece modeldeki adı aramaya çalışmakla kalmaz, aynı zamanda görünüm verilerinde de, birini bulur bulmaz, selectList'i yeniden oluşturur ve orijinal Selected'ınızı yok sayar.

Sorun şu ki, çoğu durumda, biz onu gerçekten bu şekilde kullanmıyoruz. biz sadece bir / birden çok öğe ile bir selectList oluşturmak istiyoruz Selected set true.

Elbette çözüm basit, modelde veya görünüm verilerinde olmayan bir ad kullanın. Bir eşleşme bulamadığında, orijinal selectList'i kullanacak ve orijinal Selected geçerli olacaktır.

Ama yine de mvc'nin bir koşul daha ekleyerek iyileştirmesi gerektiğini düşünüyorum

if ((defaultValue != null) && (!selectList.Any(i=>i.Selected)))
{
    selectList = GetSelectListWithDefaultValue(selectList, defaultValue, allowMultiple);
}

Çünkü, orijinal selectList'te zaten bir tane Seçilmiş varsa, bunu neden göz ardı edesiniz?

Sadece düşüncelerim.


Bu gerçekten şimdiye kadar okuduğum en iyi açıklama. Beni çok fazla baş ağrısından kurtardı. Tek yapmam gereken, viewmodel özelliğinin değerini belirlemekti ve işe yaradı. Teşekkürler.
Moses Machua

2

Önceki MVC 3 gönderisindeki kod çalışmıyor ama iyi bir başlangıç. Düzelteceğim. Bu kodu test ettim ve MVC 3 Razor C # 'da çalışıyor Bu kod, bir .model döndüren bir özelliği doldurmak için ViewModel desenini kullanır List<SelectListItem>.

Model sınıfı

public class Product
{
    public string Name { get; set; }
    public decimal Price { get; set; }
}

ViewModel sınıfı

using System.Web.Mvc;

public class ProductListviewModel
{
    public List<SelectListItem> Products { get; set; }
}

Kontrolör Yöntemi

public ViewResult List()
{
    var productList = new List<SelectListItem>();

    foreach (Product p in Products)
    {
        productList.Add(new SelectListItem
        {
            Value = p.ProductId.ToString(),
            Text = "Product: " + p.Name + " " + p.Price.ToString(),
            // To set the selected item use the following code 
            // Note: you should not set every item to selected
            Selected = true
        });
    }

    ProductListViewModel productListVM = new ProductListViewModeld();

    productListVM.Products = productList;

    return View(productListVM);
}

Görünüm

@model MvcApp.ViewModels.ProductListViewModel

@using (Html.BeginForm())
{
    @Html.DropDownList("Products", Model.Products)
}

HTML çıktısı şu şekilde olacaktır:

<select id="Products" name="Products">
    <option value="3">Product: Widget 10.00</option>
    <option value="4">Product: Gadget 5.95</option>
</select>

çıktıyı nasıl formatladığınıza bağlı olarak. Umarım bu yardımcı olur. Kod çalışıyor.


1
Bu selectedseçeneği belirlemez.
Jess

Seçili öğeyi SelectListItem kullanarak ayarlamak için Selected özelliğini true olarak ayarlayın.
wayne.blackmon

1

Bu, SelectExtensions sınıfında bir hata olarak görünür, çünkü seçilen öğe için model yerine yalnızca ViewData öğesini kontrol eder. Bu yüzden işin püf noktası, seçilen öğeyi modelden, özellik adı altında ViewData koleksiyonuna kopyalamaktır.

Bu MVC forumlarında verdiğim cevaptan alınmıştır, ayrıca Kazi's DropDownList özelliğini kullanan bir blog gönderisinde daha eksiksiz bir cevabım var ...

Bir model verildiğinde

public class ArticleType
{
   public Guid Id { get; set; }
   public string Description { get; set; }
}

public class Article
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public ArticleType { get; set; }
}

ve temel görünüm modeli

public class ArticleModel
{
     public Guid Id { get; set; }
     public string Name { get; set; }

     [UIHint("DropDownList")]
     public Guid ArticleType { get; set; }
}

Ardından aşağıdaki gibi bir DropDownList düzenleyici şablonu yazıyoruz ..

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<script runat="server">  
    IEnumerable<SelectListItem> GetSelectList()
    {
        var metaData = ViewData.ModelMetadata;
        if (metaData == null)
        {
            return null;
        }

        var selected = Model is SelectListItem ? ((SelectListItem) Model).Value : Model.ToString();
        ViewData[metaData.PropertyName] = selected;

        var key = metaData.PropertyName + "List";
        return (IEnumerable<SelectListItem>)ViewData[key];
    }
</script>
<%= Html.DropDownList(null, GetSelectList()) %>

Bu, görünüm modelinde ArticleType'ı bir SelectListItem olarak değiştirirseniz de işe yarar, ancak Kazi'nin bloguna göre bir tür dönüştürücü uygulamanız ve bağlayıcıyı bunu basit bir tür olarak ele almaya zorlamak için onu kaydetmeniz gerekir.

Denetleyicinizde o zaman ...

public ArticleController 
{
     ...
     public ActionResult Edit(int id)
     {
          var entity = repository.FindOne<Article>(id);
          var model = builder.Convert<ArticleModel>(entity);

          var types = repository.FindAll<ArticleTypes>();
          ViewData["ArticleTypeList"] = builder.Convert<SelectListItem>(types);

          return VIew(model);
     }
     ...
}

Cevabınız için teşekkürler, bunu kontrol etmem gerekecek.
blu

0

Sorun, dropbox'ların liste kutuları ile aynı şekilde çalışmamasıdır, en azından ASP.NET MVC2 tasarımının beklediği şekilde: Bir dropbox, liste kutuları birden çok değer seçimine sahip olabileceğinden, yalnızca sıfır veya bir değere izin verir. Dolayısıyla, HTML ile katı olduğundan, bu değer seçenek listesinde "seçili" işaret olarak olmamalı, girişin kendisinde olmalıdır.

Aşağıdaki örneğe bakın:

<select id="combo" name="combo" value="id2">
  <option value="id1">This is option 1</option>
  <option value="id2" selected="selected">This is option 2</option>
  <option value="id3">This is option 3</option>
</select>

<select id="listbox" name="listbox" multiple>
  <option value="id1">This is option 1</option>
  <option value="id2" selected="selected">This is option 2</option>
  <option value="id3">This is option 3</option>
</select>

Kombo, seçili seçeneğe sahiptir, ancak aynı zamanda değer özniteliği kümesine de sahiptir . Bu nedenle, ASP.NET MVC2'nin bir dropbox oluşturmasını ve belirli bir değerin seçili olmasını istiyorsanız (ör. Varsayılan değerler, vb.), İşleme sırasında buna aşağıdaki gibi bir değer vermelisiniz:

// in my view             
<%=Html.DropDownList("UserId", selectListItems /* (SelectList)ViewData["UserId"]*/, new { @Value = selectedUser.Id } /* Your selected value as an additional HTML attribute */)%>

0

ASP.NET MVC 3'te listenizi ViewData'ya ekleyebilirsiniz ...

var options = new List<SelectListItem>();

options.Add(new SelectListItem { Value = "1", Text = "1" });
options.Add(new SelectListItem { Value = "2", Text = "2" });
options.Add(new SelectListItem { Value = "3", Text = "3", Selected = true });

ViewData["options"] = options;

... ve sonra jilet görünümünüzde adıyla referans verin ...

@Html.DropDownList("options")

DropDownList çağrısında listeyi manuel olarak "kullanmanız" gerekmez. Bu şekilde yapmak benim için de seçilen değeri doğru şekilde ayarlayın.

Feragatname:

  1. Bunu web formları görüntüleme motoruyla denemedim, ancak çalışması da gerekiyor.
  2. Bunu v1 ve v2'de test etmedim, ancak işe yarayabilir.

0

İstenilen sonucu elde etmeyi başardım, ancak biraz farklı bir yaklaşımla. Açılır Listede Modeli kullandım ve sonra ona referans verdim. Aradığınız şeyin bu olduğundan emin değilim.

@Html.DropDownList("Example", new SelectList(Model.FeeStructures, "Id", "NameOfFeeStructure", Model.Matters.FeeStructures))

Yukarıdaki Model.Matters.FeeStructures benim kimliğimdir ve bu, seçilmesi gereken öğenin değeriniz olabilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.