2013-07-25 16 views
1

我的索引頁看起來是這樣的:DropDownListFor使用不帶​​參數(關閉)拉姆達時選擇錯誤的值

案例1:

@model IEnumerable<MyStats.Models.Port> 

... 
<!-- does not work --> 
@Html.DropDownListFor(modelItem => item.Active,new List<SelectListItem>(){ new SelectListItem(){ Text = "True", Value=bool.TrueString}, new SelectListItem(){ Text = "False", Value=bool.FalseString}}); 

<!-- does work --> 
@Html.EditorFor(modelItem => item.Active) 

項目是從定義枚舉MODELE一個端口型號在文件的頂部。 item.Active是一個布爾值。 不幸的是,DropDownListFor不起作用,布爾值沒有設置正確。 但EditorFor確實有效。

並在編輯窗口中,DropdownlistFor做工作: 案例2:

@model MyStats.Models.Port 
... 
@Html.DropDownListFor(model => model.Active,new List<SelectListItem>(){ new SelectListItem(){ Text = "True", Value=bool.TrueString}, new SelectListItem(){ Text = "False", Value=bool.FalseString}}) 

據我瞭解,所不同的是,在案例1 lambda表達式是一個封閉,其中item.Active存儲在裏面,在case2中,模型在運行時(在htmlhelper中的某處)傳遞給lambda表達式。 但爲什麼會有差異?它不應該因爲在case1中應該從表達式閉包中提取正確的值。 並且因爲它與EditorFor,爲什麼它不起作用DropDownListFor

回答

0

我會用:

@Html.DropDownList("Active", 
new SelectList(new List<string>() { "True", "False" }, Model.Active.ToString())) 

我認爲這是更短,更清晰。當您製作SelectList時,您可以手動指定默認值。嘗試DropDownListFor也可以使用SelectList而不是IEnumerable

@Html.DropDownList(model => model.Active, 
new SelectList(new List<string>() { "True", "False" })) 

P.S.在第一個例子中,你已經鍵入「modelItem => item.Active」而不是「modelItem => modelItem.Active」我猜。

+0

謝謝。 但modelItem => item.Active是正確的。這是參數無關緊要的lambda表達式。 其實這是自動創建的代碼。當使用asp.net mvc時。 你也可以寫「bla => item.Active」,它仍然可以工作。 bla被忽略。只有「item.Active」很重要。 「item」是範圍內的一個對象,它與lambda expr一起存儲。不知何故。在這種情況下,lambda表達式被稱爲閉包。 這就是案件之間的差異。 在case2中它是「model => model.Active」,html helper將使用原始模型在運行時從它獲取活動值。 – DanielG

2

我遇到了同樣的問題!以下是我在MVC源代碼的一些挖掘後發現:

  • 短版: 如果使用modelItem => item.Active,它不會被執行它作爲一個標準的.NET表情!相反,邏輯會注意到item.Active作爲代碼,它訪問Active屬性,並將嘗試從頁面的模型中獲取此屬性,而不是從您正在使用的項目獲取該屬性。
  • 較長版本: 下面是DropDownFor方法的源代碼:Link注意,方法使用稱爲ModelMetadata的對象,並使用ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData)創建它。 現在,如果你看ModelMetadata.FromLambdaExpressionhere,請注意,該方法不評估表達式 - 它試圖找出它的類型。你的情況,它得到

    case ExpressionType.MemberAccess: 
        // Property/field access is always legal 
        MemberExpression memberExpression = (MemberExpression)expression.Body; 
        propertyName = memberExpression.Member is PropertyInfo ? memberExpression.Member.Name : null; 
        containerType = memberExpression.Expression.Type; 
        legalExpression = true; 
        break; 
    

    在此之後,代碼將試圖訪問該頁面的模型,並從封閉不是你的項目的屬性。

    TParameter container = viewData.Model; 
    Func<object> modelAccessor =() => 
    { 
        try 
        { 
         return CachedExpressionCompiler.Process(expression)(container); 
        } 
        catch (NullReferenceException) 
        { 
         return null; 
        } 
    }; 
    

我希望這有助於!我仍然試圖找出如何解決此問題:)

+0

這有助於,謝謝 – DanielG