1

我的索引页面如下所示:

情况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)

item是来自文件顶部定义的可枚举模型的端口模型。 item.Active是一个布尔值。不幸的是,DropDownListFor不起作用,布尔值设置不正确。但EditorFor确实有效。

在编辑窗口中,DropdownlistFor确实有效:case2:

@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}})

据我了解,不同之处在于,在 case1 中,lambda 表达式是一个闭包,其中 item.Active 存储在其中,而在 case2 中,模型在运行时(在 htmlhelper 中的某个位置)传递给 lambda 表达式。但是为什么会有区别呢?这无关紧要,因为在 case1 中,应该从表达式闭包中提取正确的值。既然它适用于EditorFor,为什么它不适用于DropDownListFor

4

2 回答 2

2

我遇到了同样的问题!这是我在挖掘 MVC 源代码后发现的:

  • 短版: 如果使用modelItem => item.Active,它不会作为标准的 .NET 表达式执行!相反,逻辑会注意到item.Active代码,它访问Active属性并尝试从页面模型中获取此属性,而不是从您正在使用的项目中获取!!!!
  • 更长的版本: 这里是 DropDownFor 方法的源代码:Link请注意,该方法使用了一个名为的对象ModelMetadata,并使用ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData). 现在,如果您看ModelMetadata.FromLambdaExpression 这里,请注意该方法不计算表达式 - 它试图找出它的类型。在你的情况下,它进入

    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;
        }
    };
    

我希望这有帮助!我仍在试图弄清楚如何解决这个问题:)

于 2013-08-07T13:39:32.740 回答
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" }))

PS 在第一个示例中,我猜您输入了“modelItem => item.Active”而不是“modelItem => modelItem.Active”。

于 2013-07-25T13:11:14.167 回答