Jika menurut kami ini bukan bug yang harus diperbaiki tim, sebaiknya MSDN memperbaiki dokumen tersebut. Yang membingungkan sebenarnya berasal dari dokumen buruk ini. Di MSDN , ini menjelaskan nama parameter sebagai,
Type: System.String
The name of the form field to return.
Ini hanya berarti html terakhir yang dihasilkannya akan menggunakan parameter itu sebagai nama input pemilihan. Tapi, sebenarnya artinya lebih dari itu.
Saya kira perancang berasumsi bahwa pengguna akan menggunakan model tampilan untuk menampilkan daftar tarik-turun, juga akan menggunakan pos kembali ke model tampilan yang sama . Tetapi dalam banyak kasus, kami tidak benar-benar mengikuti asumsi itu.
Gunakan contoh di atas,
public class Person {
public int Id { get; set; }
public string Name { get; set; }
}
Jika kita mengikuti asumsinya, kita harus mendefinisikan model tampilan untuk tampilan terkait dropdownlist ini
public class PersonsSelectViewModel{
public string SelectedPersonId,
public List<SelectListItem> Persons;
}
Karena ketika memposting kembali, hanya nilai yang dipilih yang akan memposting kembali, jadi nilai yang dipilih harus diposting kembali ke properti model SelectedPersonId, yang berarti nama parameter pertama Html.DropDownList harus 'SelectedPersonId'. Jadi, desainer berpikir bahwa saat menampilkan tampilan model dalam tampilan, properti model SelectedPersonId harus menyimpan nilai default dari daftar dropdown tersebut. Meskipun List <SelectListItem> Persons Anda telah menyetel flag yang Dipilih untuk menunjukkan mana yang dipilih / default, tml.DropDownList akan benar-benar mengabaikannya dan membangun ulang IEnumerable <SelectListItem> itu sendiri dan menyetel item default / yang dipilih berdasarkan namanya.
Berikut adalah kode dari asp.net mvc
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);
}
Jadi, kode sebenarnya melangkah lebih jauh, tidak hanya mencoba mencari nama di model, tetapi juga di viewdata, segera setelah menemukannya, ia akan membangun kembali selectList dan mengabaikan Selected asli Anda.
Masalahnya adalah, dalam banyak kasus, kami tidak benar-benar menggunakannya. kami hanya ingin memasukkan selectList dengan satu / beberapa item Selected set true.
Tentu saja solusinya sederhana, gunakan nama yang tidak ada di model atau di viewdata. Jika tidak dapat menemukan kecocokan, itu akan menggunakan selectList asli dan Selected asli akan berpengaruh.
Tapi saya masih berpikir MVC harus memperbaikinya dengan menambahkan satu syarat lagi
if ((defaultValue != null) && (!selectList.Any(i=>i.Selected)))
{
selectList = GetSelectListWithDefaultValue(selectList, defaultValue, allowMultiple);
}
Karena, jika selectList asli sudah memiliki satu Selected, mengapa Anda mengabaikannya?
Hanya pikiranku.