Asp.net-Mvc

DropDownListFor 沒有綁定到帶有重複項的編輯視圖 (List<T>)

  • August 20, 2010

事情就是這樣。我有一個編輯視圖,當我打開它時它不會綁定下拉列表的值。

   [NonAction]
   public List&lt;SelectListItem&gt; VraagType() {
       List&lt;SelectListItem&gt; l = new List&lt;SelectListItem&gt;();
       SelectListItem a = new SelectListItem();
       SelectListItem b = new SelectListItem();

       a.Text = "Meerkeuze";
       a.Value = "M";

       b.Text = "Open";
       b.Value = "O";

       l.Add(a);
       l.Add(b);

       return l;
   }

   [NonAction]
   public List&lt;SelectListItem&gt; getSchalen() {
       return _db.EvalSchaals.ToList().ToSelectList(q =&gt; q.Sch_Naam, q =&gt; q.Sch_ID.ToString(), q =&gt; q.Sch_ID == -1).ToList();
   }

   public ActionResult Edit(int id) {
       ViewData["vraagtype"] = VraagType();
       ViewData["schaal"] = getSchalen();

       EvalVragenBlok evb = _db.EvalVragenBloks.First(q =&gt; q.Vrbl_ID == id);
       List&lt;EvalVragen&gt; ev = _db.EvalVragens.Where(q =&gt; q.Vrbl_ID == id).ToList();

       FlatEvalVragenBlok fevb = Mapper.Map&lt;EvalVragenBlok, FlatEvalVragenBlok&gt;(evb);
       fevb.Vragen = new List&lt;FlatEvalVragen&gt;();

       return View(fevb);
   }

這是來自控制器的程式碼。

這是來自 Edit.aspx 視圖的程式碼

       &lt;h2&gt;
           Edit&lt;/h2&gt;
       &lt;% using (Html.BeginForm()) {&#37;&gt;
       &lt;%: Html.ValidationSummary(true) %&gt;
       &lt;fieldset&gt;
           &lt;legend&gt;Fields&lt;/legend&gt;
   &lt;legend&gt;Fields&lt;/legend&gt;
           &lt;div class="editor-label"&gt;
               &lt;%: Html.LabelFor(model =&gt; model.Vrbl_Titel) %&gt;
           &lt;/div&gt;
           &lt;div class="editor-field"&gt;
               &lt;%: Html.TextBoxFor(model =&gt; model.Vrbl_Titel) %&gt;
               &lt;%: Html.ValidationMessageFor(model =&gt; model.Vrbl_Titel) %&gt;
           &lt;/div&gt;
           &lt;div class="editor-label"&gt;
               &lt;%: Html.LabelFor(model =&gt; model.Sch_ID) %&gt;
           &lt;/div&gt;
           &lt;div class="editor-field"&gt;
               &lt;%: Html.DropDownListFor(model =&gt; model.Sch_ID, ViewData["schaal"] as List&lt;SelectListItem&gt;, "Selecteer een schaal...") %&gt;
               &lt;%: Html.ValidationMessageFor(model =&gt; model.Sch_ID) %&gt;
           &lt;/div&gt;
           &lt;%= Html.ValidationMessageFor(model =&gt; model.Vragen) %&gt;
           &lt;table id="vragentbl"&gt;
               &lt;tr&gt;
                   &lt;th&gt;
                   &lt;/th&gt;
                   &lt;th&gt;
                       Vraag
                   &lt;/th&gt;
                   &lt;th&gt;
                       Soort
                   &lt;/th&gt;
               &lt;/tr&gt;
               &lt;% if (Model.Vragen != null) { &#37;&gt;
               &lt;% for (int i = 0; i &lt; Model.Vragen.Count; i++) {  %&gt;
               &lt;tr&gt;
                   &lt;td&gt;
                       &lt;%=i + 1%&gt;
                   &lt;/td&gt;
                   &lt;td&gt;
                       &lt;%= Html.TextBoxFor(model =&gt; model.Vragen[i].Evvr_Vraag, new { style = "width:400px" })%&gt;&lt;br /&gt;
                       &lt;%= Html.ValidationMessageFor(model =&gt; model.Vragen[i].Evvr_Vraag)%&gt;
                   &lt;/td&gt;
                   &lt;td&gt;
                       &lt;%= Html.DropDownListFor(model =&gt; model.Vragen[i].Evvr_Type, ViewData["vraagtype"] as List&lt;SelectListItem&gt;, new { style = "width:95px" })%&gt;&lt;br /&gt;
                       &lt;%= Html.ValidationMessageFor(model =&gt; model.Vragen[i].Evvr_Type)%&gt;
                   &lt;/td&gt;
               &lt;/tr&gt;
               &lt;% }
                  } %&gt;
               &lt;tr&gt;
                   &lt;td&gt;
                   &lt;/td&gt;
                   &lt;td&gt;
                       &lt;a id="addnew" href="#"&gt;Voeg extra keuze toe&lt;/a&gt;
                   &lt;/td&gt;
                   &lt;td&gt;
                   &lt;/td&gt;
               &lt;/tr&gt;
           &lt;/table&gt;
           &lt;p&gt;
               &lt;input type="submit" value="Save" /&gt;
           &lt;/p&gt;
       &lt;/fieldset&gt;
       &lt;% } %&gt;

我有 2 個 List 。其中1個在表單的非重複部分(Schalen),另一個(VraagType)在重複部分內部。

對於 Schalen 來說,一切正常。我打開編輯視圖,所有欄位都按原樣填寫。Vrbl_Titel 有它的值,Sch_ID 的下拉列表有它從我與視圖一起發送的對象接收到的值,該對象來自數據庫。

問題在於重複部分。model.Vragen 的文本框

$$ i $$.Evvr_Vraag 獲取它的值,以及 model.Vragen 的下拉列表$$ i $$.Evvr_Type 已顯示,但是,此下拉列表獲取在對像中發送的值。它保持它的預設標準值,這是“選擇列表”中的第一項 我如何從我的“Vragen”對像中獲取我的價值,進入下拉列表。如果我把值放在一個簡單的文本框中

&lt;%= Html.TextBoxFor(model =&gt; model.Vragen[i].Evvr_Type)%&gt;

然後文本框確實獲得了值。所以問題是下拉值不會改變它的初始值……MVC中的錯誤?

僅供參考,這是發送到視圖的對象的外觀:

       namespace MVC2_NASTEST.Models {

           public partial class FlatEvalVragenBlok {
               public int Vrbl_ID { get; set; }
               public int Sch_ID { get; set; }
               public string Vrbl_Titel { get; set; }
               public List&lt;FlatEvalVragen&gt; Vragen { get; set; }
           }
       }

       namespace MVC2_NASTEST.Models {

           public partial class FlatEvalVragen {
               public int Evvr_ID { get; set; }
               public int Vrbl_ID { get; set; }
               public int Evvr_rang { get; set; }
               public string Evvr_Vraag { get; set; }
               public char Evvr_Type { get; set; }
           }
       }

看來這確實是 ASP.NET MVC 2 中的一個錯誤或至少不一致。我檢查了它的原始碼,發現從 TextBoxFor() 助手呼叫的 InputHelper() 方法接收預設值計算

ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData).Model

但是從 DropDownListFor() 助手呼叫的 SelectInternal() 方法只接收使用 ExpressionHelper.GetExpressionText() 方法找到的控制項的名稱。

因此 SelectInternal() 嘗試使用 MVC 1 中的 ViewData.Eval() 方法查找預設值。眾所周知,此方法無法通過數字索引從數組中提取值。

所以在你的情況下適用

&lt;%: Html.DropDownListFor(model =&gt; model.Sch_ID) %&gt;
&lt;%= Html.TextBoxFor(model =&gt; model.Vragen[i].Evvr_Type)%&gt;

但不是

&lt;%: Html.DropDownListFor(model =&gt; model.Vragen[i].Evvr_Type) %&gt;

因為它相當於

&lt;%: Html.DropDownList("Vragen[" + i + "].Evvr_Type") %&gt;

同時我想再次強調什麼

&lt;%= Html.TextBoxFor(model =&gt; model.Vragen[i].Evvr_Type)%&gt;

不等於

&lt;%= Html.TextBox("model.Vragen[" + i + "].Evvr_Type")%&gt;

因為後者即使在 MVC 2 中也無法綁定預設值。

可能的解決方法

首先。由於 SelectInternal() 還檢查 ModelState 字典,因此您可以在返回視圖之前填充此字典。

for (int i=0; i &lt; fevb.Vragen.Count(); i++)
   ModelState.Add("Vragen[" + i + "].Evvr_Type", new ModelState
   {
       Value = new ValueProviderResult(fevb.Vragen[i].Evvr_Type, null, 
           CultureInfo.CurrentCulture) 
   });

這將在發布後由 MVC 自己完成,因此您應該只在第一次手動操作。

第二。代替

&lt;%= Html.DropDownListFor(model =&gt; model.Vragen[i].Evvr_Type, 
   ViewData["vraagtype"] as List&lt;SelectListItem&gt;)%&gt;

利用

&lt;%= Html.DropDownListFor(model =&gt; model.Vragen[i].Evvr_Type, 
   new SelectList(ViewData["vraagtype"] as IEnumerable, "Value", "Text",
       Model.Vragen[i].Evvr_Type))%&gt;

查看數據

$$ “vraagtype” $$在這種情況下不必包含 SelectListItem 的對象,任何 IEnumerable 就足夠了。如有需要,您可以查看 SelectList() 方法說明。

引用自:https://stackoverflow.com/questions/3501498