我如何让这个 ASP.NET MVC 选择列表工作?

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

注意如何不选择任何项目?

我该怎么办?

231501 次浏览

我就是这么做的

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

再看一眼,我不确定我知道你在找什么..。

使用接受 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") %>

可能在 ViewData 中存在一些模棱两可的地方:

看看 给你

我使用扩展方法:

用途

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

这是一个选择:

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" },
}

用你的例子来说,这对我很有用:

控制器:

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

观点:

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

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

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"]) %>

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

这确实有点奇怪,但我试过了,很有效。

因此,如果你的类有一个名为 CountryId 的字段,并且你正在显示一个国家名列表,使下拉菜单中的 id 为 CountryName 而不是 CountryId,那么在文章中,你可以使用 Collection [“ CountryName”]。

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

必须将 SelectList ctor 与 SelectListItem []、 Text-Name、 Value-Name 和 SelectedValue 一起使用。请注意传递 SelectedValue 的 SelectListItem 的 VALUE,您希望被选中,而不是 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" );

(没有测试这个,但我有同样的问题)

然后第2个选项将获得 select = “ select”属性。 它看起来像老式的数据集; -)

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");

模型中选择的值取代了默认项。 (我承认我没有读完所有的帖子)

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

我发现,正如上面某人所说的,我的选择列表不能在 mvc2中工作,因为它们被发送的 ViewData 名称与字段名称相同。

例如:

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

工作的时候

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

因为 ViewData 名称“ ForID”与它所工作的字段的名称相同,所以不能正常工作

我是这样做的:

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

一种可能的解释是,要绑定到的 selectlist 值不是字符串。

那么在这个例子中,参数‘ PageOptionsDropDown’在您的模型中是一个字符串吗?因为如果不是,那么列表中的选定值将不会显示。

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

以上所有都是一个主题的变体,即如何将一组数据发送到下拉列表的视图中,并且它们或多或少都是相同的。

问题在于视野。要么创建自己的 DropDownList 扩展方法,该方法尊重您设置的 selectvalue,要么手动迭代。这对你最有利。

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

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

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

基于 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)"选项标签:

<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 注释的 在这里发现的

简单:

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

我也有同样的问题。解决办法很简单。只需将传递给 DropDownList 帮助器的“ name”参数更改为与 ViewModel 中现有的任何属性都不匹配的内容。 点击这里阅读更多: Http://www.dotnetguy.co.uk/post/2009/06/25/net-mvc-selectlists-selected-value-does-not-get-set-in-the-view

我引用 Dan Watson 的话:

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

干杯!

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

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

或者

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

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

例如:

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

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"))

只有当您将 Area 对象的 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 属性值。

如果你想传递一些随机的文本到你的 DropDownList,例如 ——选择——,你可以很容易做到这一点使用这段代码:

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