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.