【问题标题】:How can I get this ASP.NET MVC SelectList to work?如何让这个 ASP.NET MVC SelectList 工作?
【发布时间】:2009-04-23 14:23:20
【问题描述】:

我在控制器中创建了一个 selectList,以显示在视图中。

我正在尝试动态创建它,有点像这样......

myViewData.PageOptionsDropDown = 
   new SelectList(new [] {"10", "15", "25", "50", "100", "1000"}, "15");

它可以编译,但是输出不好......

<select id="PageOptionsDropDown" name="PageOptionsDropDown">
    <option>10</option>
    <option>15</option>
    <option>25</option>
    <option>50</option>
    <option>100</option>
    <option>1000</option>
</select>

注意如何没有选择任何项目?

我该如何解决这个问题??

【问题讨论】:

标签: c# asp.net-mvc selectlist


【解决方案1】:

我就是这样做的

IList<Customer> customers = repository.GetAll<Customer>();
IEnumerable<SelectListItem> selectList = 
    from c in customers
    select new SelectListItem
    {
        Selected = (c.CustomerID == invoice.CustomerID),
        Text = c.Name,
        Value = c.CustomerID.ToString()
    };

乍一看,我不确定我知道你在追求什么......

【讨论】:

  • 谢谢你帮助我解决了这个问题。
  • 不解决选定项目的问题,但它是避免选择列表的魔术字符串的好方法!干杯
  • 要修复选中的商品问题,添加以下代码:SelectList sList = new SelectList(selectList, "Text", "Value", selected); 其中selected 是当前选中的客户
【解决方案2】:

我使用扩展方法:

用法

var departmentItems = departments.ToSelectList(d => d.Code + 
                                               " - " + d.Description,
                                               d => d.Id.ToString(),
                                               " - ");

var functionItems = customerFunctions.ToSelectList(f => f.Description, 
                                                   f => f.Id.ToString(), 
                                                   " - ");

public static class MCVExtentions
{
    public static List<SelectListItem> ToSelectList<T>(
        this IEnumerable<T> enumerable, 
        Func<T, string> text, 
        Func<T, string> value, 
        string defaultOption)
    {
        var items = enumerable.Select(f => new SelectListItem()
                                     {
                                         Text = text(f), 
                                         Value = value(f) 
                                     }).ToList();
        items.Insert(0, new SelectListItem()
                    {
                        Text = defaultOption, 
                        Value = "-1" 
                    });
        return items;
    }
}

【讨论】:

  • 不错。我添加了一个选定的 Func、一个 defaultValue 选项和一个第二个重载,没有指定任何默认值,这是一种享受。顺便说一句,如果你想让返回类型 IEnumerable 你可以使用 yield return 语法来让这个看起来很干净
【解决方案3】:

使用接受items, dataValueField, dataTextField, selectedValue作为参数的构造函数:

ViewData["myList"] = 
                new SelectList(new[] { "10", "15", "25", "50", "100", "1000" }
                .Select(x => new {value = x, text = x}), 
                "value", "text", "15");

那么在你看来:

<%=Html.DropDownList("myList") %>

【讨论】:

  • 好兄弟 :) 我喜欢!我正在尝试这样做..但我无法获得 .Select(..) 部分..很好:)我会在家里尝试一下,稍后:)
  • 嘿卡格达斯。效果很好,除了未选择所选字段。任何想法?这是 MVC 中的错误吗?
  • 当您将 SelectList 项添加到 ViewData 对象中时(如 ViewData["myList"] = new SelectList ..),然后使用 。但是,如果不这样做,我将无法使所选项目工作。很奇怪。
  • @Cagdas - 再次嗨伙计..我还没有弄清楚:( ViewData 这是什么???我有一个具有自己属性的强类型 ViewData .... ?? ?
  • @Pure.Krome - 我从问题中的示例中获取了该属性。现在我正在编辑代码示例。请在几秒钟后查看我的编辑。
【解决方案4】:

根据 Thomas Stock 的回答,我创建了这些重载的 ToSelectList 方法:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;

public static partial class Helpers
{
    public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, bool selectAll = false)
    {
        return enumerable.ToSelectList(value, value, selectAll);
    }

    public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, object selectedValue)
    {
        return enumerable.ToSelectList(value, value, new List<object>() { selectedValue });
    }

    public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, IEnumerable<object> selectedValues)
    {
        return enumerable.ToSelectList(value, value, selectedValues);
    }

    public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, Func<T, object> text, bool selectAll = false)
    {
        foreach (var f in enumerable.Where(x => x != null))
        {
            yield return new SelectListItem()
            {
                Value = value(f).ToString(),
                Text = text(f).ToString(),
                Selected = selectAll
            };
        }
    }

    public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, Func<T, object> text, object selectedValue)
    {
        return enumerable.ToSelectList(value, text, new List<object>() { selectedValue });
    }

    public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, Func<T, object> text, IEnumerable<object> selectedValues)
    {
        var sel = selectedValues != null
            ? selectedValues.Where(x => x != null).ToList().ConvertAll<string>(x => x.ToString())
            : new List<string>();

        foreach (var f in enumerable.Where(x => x != null))
        {
            yield return new SelectListItem()
            {
                Value = value(f).ToString(),
                Text = text(f).ToString(),
                Selected = sel.Contains(value(f).ToString())
            };
        }
    }
}

在您的控制器中,您可以执行以下操作:

var pageOptions = new[] { "10", "15", "25", "50", "100", "1000" };
ViewBag.PageOptions = pageOptions.ToSelectList(o => o, "15" /*selectedValue*/);

最后在你的视图中,输入:

@Html.DropDownList("PageOptionsDropDown", ViewBag.PageOptions as IEnumerable<SelectListItem>, "(Select one)")

它会得到想要的输出——当然,如果你不想要第一个空项目,你可以省略上面的"(Select one)" optionLabel:

<select id="PageOptionsDropDown" name="PageOptionsDropDown">
<option value="">(Select one)</option>
<option value="10">10</option>
<option selected="selected" value="15">15</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
<option value="1000">1000</option>
</select>

更新:修改后的代码清单可以是带有 XML cmets 的 found here

【讨论】:

    【解决方案5】:

    问题是,SelectList 按设计工作。错误在设计中。 您可以在 SelectedItem 中设置 Selected 属性,但这将完全被忽略, 如果您使用 GetEnumerator() 遍历列表(或者如果 Mvc 为您执行此操作)。 Mvc 将改为创建新的 SelectListItems。

    您必须将 SelectList ctor 与 SelectListItem[]、Text-Name、Value-Name 和 SelectedValue 一起使用。请注意,将要选择的 SelectListItem 的 VALUE 作为 SelectedValue 传递,而不是 SelectListItem 本身! 示例:

    SelectList sl = new SelectList( new[]{
      new SelectListItem{ Text="one", Value="1"},
      new SelectListItem{ Text="two", Value="2"},
      new SelectListItem{ Text="three", Value="3"}
    }, "Text", "Value", "2" );
    

    (没有测试过,但我遇到了同样的问题)

    那么第二个选项将获得 selected="selected" 属性。 这看起来像是不错的旧数据集;-)

    【讨论】:

      【解决方案6】:

      这是一个选项:

      myViewData.PageOptionsDropDown = new[] 
      {
       new SelectListItem { Text = "10", Value = "10" },
       new SelectListItem { Text = "15", Value = "15", Selected = true }
       new SelectListItem { Text = "25", Value = "25" },
       new SelectListItem { Text = "50", Value = "50" },
       new SelectListItem { Text = "100", Value = "100" },
       new SelectListItem { Text = "1000", Value = "1000" },
      }
      

      【讨论】:

      • new SelectListItem { Selected=true, Text = "15", Value = "15" } 为所选值。
      • 哎呀,是的,忘记包含“选定”属性,谢谢Cadoo =)
      【解决方案7】:

      如果这就是您想要做的所有事情,那么只需将数组声明为字符串即可解决所选项目问题:

      myViewData.PageOptionsDropDown = 
         new SelectList(new string[] {"10", "15", "25", "50", "100", "1000"}, "15");
      

      【讨论】:

        【解决方案8】:

        让 SelectList 和 SelectedValue 一起工作非常简单,即使您的属性不是像 Int、String 或 Double 值这样的简单对象。

        例子:

        假设我们的 Region 对象是这样的:

        public class Region {
             public Guid ID { get; set; }
             public Guid Name { get; set; }
        }
        

        您的视图模型类似于:

        public class ContactViewModel {
             public DateTime Date { get; set; }
             public Region Region { get; set; }
             public List<Region> Regions { get; set; }
        }
        

        你可以有下面的代码:

        @Html.DropDownListFor(x => x.Region, new SelectList(Model.Regions, "ID", "Name")) 
        

        仅当您将 Region 对象的 ToString 方法覆盖为以下内容时:

        public class Region {
             public Guid ID { get; set; }
             public Guid Name { get; set; }
        
             public override string ToString()
             {
                 return ID.ToString();
             }
        }
        

        这有 100% 的保证工作。

        但我真的相信让 SelectList 在所有情况下都 100% 工作的最佳方法是使用 Equals 方法针对项目集合上的每个项目测试 DropDownList 或 ListBox 属性值。

        【讨论】:

          【解决方案9】:

          如果您有一个强类型视图,您似乎需要更改下拉列表的 ID,以便它不是继承类上的属性名称。然后,您需要在您的编辑 (POST) 方法中添加一些逻辑,以便在提交更改之前从 FORMCollection 中提取所选值并将其放到您的实例中。

          这当然有点奇怪,但我试过了,它确实有效。

          因此,如果您的班级有一个名为 CountryId 的字段,并且您正在显示国家/地区名称列表,请让下拉列表的 ID 为 CountryName 而不是 CountryId,然后在帖子中,您可以使用 Collection["国家名称”]。

          【讨论】:

          • 是的,我也遇到了同样的问题。只需更改名称即可。谢谢!
          【解决方案10】:

          我遇到了完全相同的问题。解决方案很简单。只需将传递给 DropDownList 助手的“名称”参数更改为与 ViewModel 中存在的任何属性都不匹配的内容。 在这里阅读更多: http://www.dotnetguy.co.uk/post/2009/06/25/net-mvc-selectlists-selected-value-does-not-get-set-in-the-view

          我引用丹·沃森的话:

          在 MVC 中,如果视图是强类型的,则选择列表的 selected 选项将被覆盖,并且在构造函数上设置的 selected 选项属性将永远不会到达视图,而是会选择下拉列表中的第一个选项(为什么仍然有点一个谜)。

          干杯!

          【讨论】:

            【解决方案11】:

            所有这些答案看起来都很棒,但似乎是控制器正在以众所周知的结构化格式为视图准备数据,而不是让视图简单地迭代通过模型传递的 IEnumerable 并构建标准选择列表然后让 DefaultModelBinder 通过操作参数将选定的项目返回给您。是的,不,为什么不呢?关注点分离,是吗?让控制器构建特定于 UI 和 View 的东西似乎很奇怪。

            【讨论】:

              【解决方案12】:

              简单:

              string[] someName = new string[] {"10", "15", "25", "50", "100", "1000"};
              myViewData.PageOptionsDropDown = new SelectList(someName, "15");
              

              【讨论】:

                【解决方案13】:

                我就是这样运行的,没有任何问题,

                public class myViewDataObj
                    {
                        public SelectList PageOptionsDropDown { get; set; }
                    }
                
                public ActionResult About()
                        {
                            myViewDataObj myViewData = new myViewDataObj();
                            myViewData.PageOptionsDropDown =
                                  new SelectList(new[] { "10", "15", "25", "50", "100", "1000" }, "15");
                
                            ViewData["myList"] = myViewData.PageOptionsDropDown;
                            return View();
                        }
                

                <%=Html.DropDownList("myList") %>
                

                如果你这样做,它也有效,

                public ActionResult About()
                        {
                            myViewDataObj myViewData = new myViewDataObj();
                            myViewData.PageOptionsDropDown =
                                  new SelectList(new[] { "10", "15", "25", "50", "100", "1000" });
                
                            ViewData["myListValues"] = myViewData.PageOptionsDropDown;
                            ViewData["myList"] = "15";
                            return View();
                        }
                

                <%=Html.DropDownList("myList",(IEnumerable<SelectListItem>)ViewData["myListValues"]) %>
                

                【讨论】:

                  【解决方案14】:

                  使用你的例子这对我有用:

                  控制者:

                  ViewData["PageOptionsDropDown"] = new SelectList(new[] { "10", "15", "25", "50", "100", "1000" }, "15");
                  

                  查看:

                  <%= Html.DropDownList("PageOptionsDropDown")%>
                  

                  【讨论】:

                  • 是的,这也对我有用。在我的例子中,列表是一个实体模型对象。控制器:ViewData["Categories"] = new SelectList(db.Categories.ToList(), "CategoryId", "CategoryName", "15");视图:Html.DropDownList("CategoryId", (SelectList)ViewData["Categories"], "--select--")
                  【解决方案15】:
                  MonthRepository monthRepository = new MonthRepository();
                  IQueryable<MonthEntity> entities = monthRepository.GetAllMonth();
                  List<MonthEntity> monthEntities = new List<MonthEntity>();
                  
                  foreach(var r in entities)
                  {
                      monthEntities.Add(r);
                  }
                  
                  ViewData["Month"] = new SelectList(monthEntities, "MonthID", "Month", "Mars");
                  

                  【讨论】:

                    【解决方案16】:

                    我是这样做的:

                    List<SelectListItem> list = new List<SelectListItem>{
                    new SelectListItem {Selected = true, Text = "Select", Value = "0"},
                    new SelectListItem {Selected = true, Text = "1", Value = "1"},
                    new SelectListItem {Selected = true, Text = "2", Value = "2"}
                    };
                    return list.ToArray();
                    

                    ToArray() 可以解决这些问题。

                    【讨论】:

                      【解决方案17】:

                      如果您想向 DropDownList 传递一些随机文本,例如 --Select--,您可以使用以下代码轻松完成:

                      @Html.DropDownListFor(x => x.CategoryId, new SelectList(Model.Categories, "Id", "Name"), "--Select--", new { @class = "form-control" })
                      

                      【讨论】:

                        【解决方案18】:

                        您的 ViewData 中可能存在一些歧义:

                        看看Here

                        【讨论】:

                          【解决方案19】:

                          模型中选择的值代替了默认项。 (我同意我没有阅读所有帖子)

                          【讨论】:

                            【解决方案20】:

                            我不记得 mvc 1 是如何设置的,但它似乎希望选择列表的名称与其所属的字段相同...

                            我发现,正如上面所说的那样,当发送的 ViewData 与字段命名相同时,我的选择列表在 mvc2 中不起作用。

                            例如:

                            &lt;%= Html.DropDownListFor((model =&gt; model.ForID), (SelectList)ViewData["ForName"]) %&gt;

                            工作时

                            &lt;%= Html.DropDownListFor((model =&gt; model.ForID), (SelectList)ViewData["ForID"]) %&gt;

                            不起作用,因为 ViewData 名称“ForID”的名称与其工作的字段相同

                            【讨论】:

                              【解决方案21】:

                              一种可能的解释是您绑定的选择列表值不是字符串。

                              那么在该示例中,参数“PageOptionsDropDown”是模型中的字符串吗?因为如果不是,则不会显示列表中的选定值。

                              【讨论】:

                                【解决方案22】:

                                如果您在 Html.DropDownList 扩展方法中查看 MVC 2 的源代码,它从不检查 SelectList 类的 SelectedValue 属性。它只会尝试与您的模型匹配。

                                以上所有内容都是主题的变体,即如何将一堆数据发送到视图以作为下拉列表以及它们都彼此一样好(或多或少)。

                                问题出在视图中。要么创建你自己的 DropDownList 扩展方法,它尊重你设置的选择值,要么手动迭代。哪个最适合您。

                                【讨论】:

                                • @Franz Antesberger 说了很多同样的话。
                                【解决方案23】:

                                如果你的模型中有一个集合并且你的视图是强类型的,那么它的一些变体将起作用:

                                @Html.DropDownListFor(x => x.RegionID, 
                                    new SelectList(Model.Regions,"RegionID", "RegionName", Model.RegionID))
                                

                                -或-

                                @Html.DropDownList("RegionID", 
                                    new SelectList(Model.Regions, "RegionID", "RegionName", Model.RegionID))
                                

                                【讨论】:

                                  猜你喜欢
                                  • 2020-07-31
                                  • 2023-03-15
                                  • 1970-01-01
                                  • 2020-08-16
                                  • 2015-01-01
                                  • 1970-01-01
                                  • 2013-03-10
                                  • 2014-11-09
                                  • 2011-04-17
                                  相关资源
                                  最近更新 更多