17

我正在使用 ASP.NET MVC 3,只是使用DropDownListForHTML Helper 遇到了一个“问题”。

我在我的控制器中这样做:

ViewBag.ShippingTypes = this.SelectListDataRepository.GetShippingTypes();

GetShippingTypes方法:

public SelectList GetShippingTypes()
{
    List<ShippingTypeDto> shippingTypes = this._orderService.GetShippingTypes();

    return new SelectList(shippingTypes, "Id", "Name");
}

我把它放在模型中ViewBag而不是模型中的原因(我对每个视图都有强类型模型),是因为我有一个使用 EditorTemplate 呈现的项目集合,它还需要访问 ShippingTypes 选择列表。

否则我需要遍历整个集合,然后分配一个 ShippingTypes 属性。

到现在为止还挺好。

在我看来,我这样做:

@Html.DropDownListFor(m => m.RequiredShippingTypeId, ViewBag.ShippingTypes as SelectList)

RequiredShippingTypeId是类型Int32

发生的情况是,下拉列表RequiredShippingTypeId未选择 的值。

我遇到了这个:http ://web.archive.org/web/20090628135923/http://blog.benhartonline.com/post/2008/11/24/ASPNET-MVC-SelectList-selectedValue-Gotcha.aspx

他建议,MVC将从ViewData“选择列表”从中查找所选值ViewData。我不确定情况是否如此,因为博客文章很旧而且他在谈论 MVC 1 beta。

解决此问题的解决方法是:

@Html.DropDownListFor(m => m.RequiredShippingTypeId, new SelectList(ViewBag.ShippingTypes as IEnumerable<SelectListItem>, "Value", "Text", Model.RequiredShippingTypeId.ToString()))

最后我试着不ToString打开RequiredShippingTypeId,这给了我和以前一样的行为:没有选择项目。

我认为这是一个数据类型问题。最终,HTML 助手将字符串(在选择列表中)与Int32(来自RequiredShippingTypeId)进行比较。

ViewBag但是,为什么将 SelectList 放入- 当它在将其添加到模型时完美工作时它不起作用,并在视图中执行此操作:

@Html.DropDownListFor(m => m.Product.RequiredShippingTypeId, Model.ShippingTypes)
4

5 回答 5

32

这不起作用的原因是由于助手的限制:只有当这个 lambda 表达式是一个简单的属性访问表达式DropDownListFor时,它才能使用作为第一个参数传递的 lambda 表达式来推断选定的值。例如,这不适用于数组索引器访问表达式,这是您的情况,因为编辑器模板。

你基本上有(不包括编辑器模板):

@Html.DropDownListFor(
    m => m.ShippingTypes[i].RequiredShippingTypeId, 
    ViewBag.ShippingTypes as IEnumerable<SelectListItem>
)

不支持以下内容:m => m.ShippingTypes[i].RequiredShippingTypeId。它仅适用于简单的属性访问表达式,但不适用于索引集合访问。

您找到的解决方法是解决此问题的正确方法,方法是在构建SelectList.

于 2012-06-15T06:36:59.577 回答
0

这可能很愚蠢,但是将其添加到您视图中的变量中是否有任何作用?

var shippingTypes = ViewBag.ShippingTypes;

@Html.DropDownListFor(m => m.Product.RequiredShippingTypeId, shippingTypes)
于 2012-06-15T01:48:29.450 回答
0

@html.DropdownList 有一个重载方法来处理这个问题。有另一种方法可以在 HTML 下拉列表中设置选定的值。

@Html.DropDownListFor(m => m.Section[b].State, 
              new SelectList(Model.StatesDropdown, "value", "text", Model.Section[b].State))

我能够从模型中获得选定的值。

"value", "text", Model.Section[b].State本节上面的语法将 selected 属性添加到从 Controller 加载的值中

于 2016-12-30T06:07:18.630 回答
0

您可以为复杂类型的每个下拉列表字段创建动态视图数据而不是视图袋。希望这会给你提示如何做到这一点

      @if (Model.Exchange != null)
                                {
                                    for (int i = 0; i < Model.Exchange.Count; i++)
                                    {
                                        <tr>
                                            @Html.HiddenFor(model => model.Exchange[i].companyExchangeDtlsId)
                                            <td>
                                                 
                                                @Html.DropDownListFor(model => model.Exchange[i].categoryDetailsId, ViewData["Exchange" + i] as SelectList, " Select category", new { @id = "ddlexchange", @class = "form-control custom-form-control required" })
                                                @Html.ValidationMessageFor(model => model.Exchange[i].categoryDetailsId, "", new { @class = "text-danger" })
                                            </td>
                                            <td>
                                                @Html.TextAreaFor(model => model.Exchange[i].Address, new { @class = "form-control custom-form-control", @style = "margin:5px;display:inline" })
                                            
                                                @Html.ValidationMessageFor(model => model.Exchange[i].Address, "", new { @class = "text-danger" })
                                            </td>
                                        </tr>
                                    }

                                }

  ViewModel CompanyDetail = companyDetailService.GetCompanyDetails(id);
               if (CompanyDetail.Exchange != null)
                for (int i = 0; i < CompanyDetail.Exchange.Count; i++)
                {
                    ViewData["Exchange" + i]= new SelectList(companyDetailService.GetComapnyExchange(), "categoryDetailsId", "LOV", CompanyDetail.Exchange[i].categoryDetailsId);
                }

于 2017-01-10T08:58:10.643 回答
0

我只是被这个限制击中并想出了一个简单的解决方法。刚刚定义的扩展方法在内部SelectList使用正确的选定项生成。

public static class HtmlHelperExtensions
{
    public static MvcHtmlString DropDownListForEx<TModel, TProperty>(
       this HtmlHelper<TModel> htmlHelper,
       Expression<Func<TModel, TProperty>> expression,
       IEnumerable<SelectListItem> selectList,
       object htmlAttributes = null)
    {
        var selectedValue = expression.Compile().Invoke(htmlHelper.ViewData.Model);
        var selectListCopy = new SelectList(selectList.ToList(), nameof(SelectListItem.Value), nameof(SelectListItem.Text), selectedValue);

        return htmlHelper.DropDownListFor(expression, selectListCopy, htmlAttributes);
    }
}

最好的事情是这个扩展可以像原来一样使用DropDownListFor

@for(var i = 0; i < Model.Items.Count(); i++)
{
   @Html.DropDownListForEx(x => x.Items[i].CountryId, Model.AllCountries)
}
于 2017-02-09T13:52:09.403 回答