【问题标题】:DropDownListFor in EditorTemplate not selecting valueEditorTemplate 中的 DropDownListFor 未选择值
【发布时间】:2010-12-27 08:26:04
【问题描述】:

我有一个自定义对象的编辑器模板。在该编辑器模板中,我使用了几个 DropDownListFor 助手。在它们中的每一个中,我都指定了一个唯一的模型属性(具有预选值)和包含所有选择选项的选择列表。

例子:

<%=Html.DropDownListFor(m => m.DocumentCategoryType, Model.DocumentCategoryTypeList) %>

我知道正在填充选项值(从查看源代码),并且我的模型使用正确的 ID 值 (DocumentCategoryType) 传入。

当视图被渲染时,我的下拉列表中没有选择的项目,因此它默认为第一个(未选择的)值。

有人有什么想法吗?

谢谢。

【问题讨论】:

标签: asp.net-mvc


【解决方案1】:

我们还通过填充一个新的SelectList 来解决该解决方案,该SelectList 已选择适当的SelectListItem,但创建了此扩展方法以使对DropDownListFor 的调用更简洁:

public static SelectList MakeSelection(this SelectList list, object selection)
{
    return new SelectList(list.Items, list.DataValueField, list.DataTextField, selection);
}

那么你的DropDownListFor 电话就变成了:

<%= Html.DropDownListFor(m => m.DocumentCategoryType, Model.DocumentCategoryTypeList.MakeSelection(Model.DocumentCategoryType)) %>

【讨论】:

  • +1 不过这确实没有必要,有谁知道这是否仍然被认为是一个错误?
  • 第二个参数的“m”如何仍在范围内?此代码为我抛出“当前上下文中不存在名称'm'”错误
【解决方案2】:

查看 ASP.NET MVC 2 源代码可以找到一些解决此问题的方法。本质上,SelectList 中的任何 SelectListItem 传递给将 Selected 属性设置为 true 的辅助扩展方法不会与使用应用于项目的 selected 属性呈现的 &lt;option&gt; 元素有任何关系。

&lt;option&gt; 元素上的selected 属性由

确定

1) 检查辅助扩展方法是否传递了SelectList。如果为空,框架将在 ViewData 中查找与键对应的值,该键是您希望为其呈现下拉列表的视图模型属性。如果值为SelectList,则这将用于呈现&lt;select&gt;,包括获取任何选定的值,只要模型属性的模型状态为空。

2) 如果在辅助扩展方法中传递了SelectList 并且模型属性的模型状态为空,则框架将在 ViewData 中查找默认值,使用模型属性名称作为键。视图数据中的值被转换为字符串,并且SelectList 中的任何项传递给辅助扩展方法的值(如果未设置值,则将检查文本)与默认值匹配将具有Selected 属性设置为 true,这反过来将呈现一个带有属性 selected="selected"&lt;option&gt;

把这些放在一起,我可以看到有两个合理的选项可以选择一个选项并使用强类型 DropDownListFor

使用以下视图模型

public class CategoriesViewModel
{
    public string SelectedCategory { get; private set ; }
    public ICollection<string> Categories { get; private set; }

    public CategoriesViewModel(string selectedCategory, ICollection<string> categories)
    {
        SelectedCategory = selectedCategory;
        Categories = categories;
    }
}

选项 1

在控制器的 ViewData 中设置一个值,根据用于呈现下拉列表的集合的属性名称来呈现您的视图

控制器动作

public class CategoriesController
{
    [HttpGet]
    public ViewResult Select()
    {
        /* some code that gets data from a datasource to populate the view model  */
        ICollection<string> categories = repository.getCategoriesForUser();
        string selectedCategory = repository.getUsersSelectedCategory();

        CategoriesViewModel model = new CategoriesViewModel(selectedCategory, categories);
        this.ViewData["Categories"] = selectedCategory;        

        return View(model);
    }

    [HttpPost]
    public ActionResult Select(CategoriesViewModel model)
    {
        /* some code that does something */
    }
}

在强类型视图中

<%: Html.DropDownListFor(m => m.Categories, Model.Categories.Select(c => new SelectListItem { Text = c, Value = c }), new { @class = "my-css-class" }) %>

选项 2

使用所选项目的属性名称呈现下拉列表

控制器动作

public class CategoriesController
{
    [HttpGet]
    public ViewResult Select()
    {
        /* some code that gets data from a datasource to populate the view model  */
        ICollection<string> categories = repository.getCategoriesForUser();
        string selectedCategory = repository.getUsersSelectedCategory();

        CategoriesViewModel model = new CategoriesViewModel(selectedCategory, categories);

        return View(model);
    }

    [HttpPost]
    public ActionResult Select(CategoriesViewModel model)
    {
        /* some code that does something */
    }
}

在强类型视图中

<%: Html.DropDownListFor(m => m.SelectedCategory, Model.Categories.Select(c => new SelectListItem { Text = c, Value = c }), new { @class = "my-css-class" }) %>

【讨论】:

【解决方案3】:

已确认为错误@aspnet.codeplex.com 并且只对强类型视图表现出这样的行为。

解决方法:在视图代码中填充您的 SelectList

喜欢

<%= Html.DropDown("DocumentCategoryType", new SelectList(Model.Categories,"id","Name",Model.SelectedCategory")) =>

【讨论】:

  • 这是有道理的。我真的很希望能够在我的模型中完成所有这些工作,然后再通过。希望他们能在 RTM 之前发现并修复它。你碰巧有这个错误的链接吗?
  • 不知道实际的错误链接,但这个问题也在 asp.net 站点的论坛中讨论过:forums.asp.net/p/1528524/4049618.aspx#3840473
  • 这对我有用。好东西。在他们正确修复之前,我可以忍受这个。
  • 这不是错误。您的选择列表名称不能与模型名称冲突。见[1]:asp.net/mvc/tutorials/javascript/…[2]:blogs.msdn.com/b/rickandy/archive/2012/01/09/…
  • 很好,自从那个问题以来,我们已经有了另外 3 个版本的 mvc (-:
【解决方案4】:

哎呀。我最终像这样解决了它。我希望 RTM 能解决这个问题。

   <%if(Model!=null){ %>
        <%= Html.DropDownListFor(m => m.DocumentCategoryType, new SelectList(Model.DocumentCategoryTypeList,"Value","Text", Model.DocumentCategoryType))%>
        <%}else{%>
            <%=Html.DropDownListFor(m => m.DocumentCategoryType, Model.DocumentCategoryTypeList) %>
        <%}%>

【讨论】:

  • 不,错误仍然存​​在。也是一个相当愚蠢的人。 dogfooding怎么了?
  • 我吃我的狗粮。此代码直接从我的工作应用程序中粘贴出来。
【解决方案5】:

确保在将 m.DocumentCategoryType 发送到视图时为其分配了一个值。

通常,当您进行回发时,该值会被重置,因此您只需指定该值 回到你的视野时。

创建下拉列表时,您需要向其传递两个值。 1. 这是您将存储所选值的位置 2. 是实际列表

例子

<%=Html.DropDownListFor(m => m.DocumentCategoryType, Model.DocumentCategoryTypeList) %>

我错误地将选择列表项 Selected 值设置为 True。这不会做任何事情。相反,只需在控制器中为 m.DocumentCategoryType 分配一个值,这实际上会为您进行选择。

【讨论】:

    【解决方案6】:

    如果您的下拉列表的来源是 IEnumerable 而不是 SelectList,这是另一个很好的解决方案:

    public static SelectList MakeSelection(this IEnumerable<SelectListItem> list, object selection, string dataValueField = "Value", string dataTextField = "Text")
    {
        return new SelectList(list, dataValueField, dataTextField, selection);
    }
    

    【讨论】:

      【解决方案7】:
      Model.DocumentCategoryTypeList
      

      这可能是你的问题。在 SelectListItems 上,是否将值设置为 .ToString() 输出?

       var list = new List<SelectListItem>()
                                 {
                                     new SelectListItem()
                                         {
                                             Value = Category.Book.ToString(),
                                             Text = "Book"                                     
                                         },
                                     new SelectListItem()
                                         {
                                             Value = Category.BitsAndPieces.ToString(),
                                             Text = "Bits And Pieces"                            },
                                     new SelectListItem()
                                         {
                                             Value = Category.Envelope.ToString(),
                                             Text = "Envelopes"                              }
                                 };
      

      这样做后对我有用。它只需要能够匹配对象中的值

      【讨论】:

      • 谢谢,我所有的值和要绑定的模型属性都已经是字符串了。
      • 刚刚意识到下拉菜单在视图中,所以我错了。我更改为 EditorTemplate,但它停止工作。
      【解决方案8】:

      我设法通过以下方式解决了同样的问题:

      new SelectList(sections.Select(s => new { Text = s.SectionName, Value = s.SectionID.ToString() }), "Value", "Text")
      

      这个技巧是将值转换为字符串。我知道这在之前的答案中已经提到过,但我发现我的解决方案更简洁:)。希望这会有所帮助。

      【讨论】:

        【解决方案9】:

        从我的项目中复制并粘贴:

        <%= Html.DropDownListFor(m => m.Profession.Profession_id, new SelectList(Model.Professions, "Profession_id", "Profession_title"),"-- Profession --")%>
        

        通过的模型:

           ...
                    public Profession Profession { get; set; }
                    public IList<Profession> Professions { get; set; }
            ...
        

        生成的 HTML:

          <select id="Profession_Profession_id" name="Profession.Profession_id">
            <option value="">-- Profesion --</option>
            <option value="4">Informatico</option>
            <option selected="selected" value="5">Administracion</option>
            </select> 
        

        为我工作。我在表单上有这个,唯一的缺点是如果模型无效并且我将模型返回到视图中,我必须重新加载职业列表。

        obj.Professions = ProfileService.GetProfessions();
        return View(obj);
        

        【讨论】:

          【解决方案10】:

          我也遇到了与字段 ProgramName 相关的问题。原来我们在 BaseController 和 Layout.cshtml 中使用了 ViewBag.ProgramName,这是出于不同的目的。由于在下拉列表中未找到 ViewBag.ProgramName 中的值,因此即使 SelectListItem.Selected 对于列表中的一项为真,也没有选择任何值。我们只是将 ViewBag 更改为使用不同的密钥,然后问题就解决了。

          【讨论】:

            【解决方案11】:

            Here is a drop-in DropDownListFor replacement 与原始 MVC 源代码略有不同。

            例子:

            <%=Html.FixedDropDownListFor(m => m.DocumentCategoryType, 
                Model.DocumentCategoryTypeList) %>
            

            【讨论】:

              【解决方案12】:

              我担心复制这么多我的 selectList 的性能,所以我将 selectedvalue 添加为自定义属性,然后使用 jquery 实际执行项目选择:

              @Html.DropDownListFor(item => item.AttendeeID, attendeeChoices, String.Empty, new { setselectedvalue = Model.AttendeeID })
              
              ........
              
              
              jQuery("select[setselectedvalue]").each(function () { e = jQuery(this); e.val(e.attr("setselectedvalue")); });
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多