127

我在控制器中创建了一个 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>

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

我怎样才能解决这个问题??

4

23 回答 23

127

我就是这样做的

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

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

于 2009-04-23T14:33:06.210 回答
68

我使用扩展方法:

用法

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;
    }
}
于 2009-05-18T13:49:12.880 回答
48

使用接受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") %>
于 2009-04-23T14:35:34.923 回答
19

根据 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 注释的修改后的代码清单。

于 2011-03-04T02:33:09.843 回答
13

问题是,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" 属性。这看起来像很好的旧数据集;-)

于 2009-08-06T18:15:41.907 回答
11

这是一个选项:

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" },
}
于 2009-06-24T16:50:18.023 回答
10

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

myViewData.PageOptionsDropDown = 
   new SelectList(new string[] {"10", "15", "25", "50", "100", "1000"}, "15");
于 2011-01-15T18:02:30.473 回答
7

It's very simple to get SelectList and SelectedValue working together, even if your property isn't a simple object like a Int, String or a Double value.

Example:

Assuming our Region object is something like this:

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

And your view model is something like:

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

You can have the code below:

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

Only if you override the ToString method of Region object to something like:

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

     public override string ToString()
     {
         return ID.ToString();
     }
}

This have 100% garantee to work.

But I really believe the best way to get SelectList 100% working in all circustances is by using the Equals method to test DropDownList or ListBox property value against each item on items collection.

于 2012-07-28T23:08:30.703 回答
5

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

这当然有点奇怪,但我尝试过它并且它有效。

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

于 2009-07-28T11:23:43.420 回答
4

我有同样的问题。解决方案很简单。只需将传递给 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 选项属性将永远不会到达视图,而是会选择下拉列表中的第一个选项(为什么仍然有点神秘) .

干杯!

于 2011-09-05T18:01:45.407 回答
3

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

于 2011-01-26T19:38:10.697 回答
3

简单的:

string[] someName = new string[] {"10", "15", "25", "50", "100", "1000"};
myViewData.PageOptionsDropDown = new SelectList(someName, "15");
于 2011-08-17T23:44:13.997 回答
2

我只是这样运行它,没有任何问题,

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"]) %>
于 2009-07-21T13:21:42.540 回答
1
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");
于 2010-03-16T12:35:10.923 回答
1

使用您的示例,这对我有用:

控制器:

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

看法:

<%= Html.DropDownList("PageOptionsDropDown")%>
于 2009-06-26T17:26:24.463 回答
1

我这样做:

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() 负责处理这些问题。

于 2010-09-30T07:55:25.153 回答
1

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

@Html.DropDownListFor(x => x.CategoryId, new SelectList(Model.Categories, "Id", "Name"), "--Select--", new { @class = "form-control" })
于 2016-01-04T17:50:58.837 回答
0

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

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

例如:

<%= Html.DropDownListFor((model => model.ForID), (SelectList)ViewData["ForName"]) %>

什么时候工作

<%= Html.DropDownListFor((model => model.ForID), (SelectList)ViewData["ForID"]) %>

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

于 2010-04-14T04:43:51.237 回答
0

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

看看这里

于 2009-04-23T14:42:05.953 回答
0

模型中选择的值会利用而不是默认项。(我同意我没有阅读所有帖子)

于 2010-03-28T16:33:43.037 回答
0

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

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

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

于 2011-01-03T15:39:17.957 回答
0

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

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

-或者-

@Html.DropDownList("RegionID", 
    new SelectList(Model.Regions, "RegionID", "RegionName", Model.RegionID))
于 2011-09-30T17:17:16.147 回答
0

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

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

于 2010-12-13T03:58:00.413 回答