为什么ListBox不选择项目,但ListBox是?

时间:2010-02-22 04:44:20

标签: asp.net-mvc listbox

我在视图中有以下代码:

<%= Html.ListBoxFor(c => c.Project.Categories,
        new MultiSelectList(Model.Categories, "Id", "Name", new List<int> { 1, 2 }))%>

<%= Html.ListBox("MultiSelectList", 
        new MultiSelectList(Model.Categories, "Id", "Name", new List<int> { 1, 2 }))%>

唯一的区别是第一个帮助器是强类型(ListBoxFor),而它无法显示所选项目(1,2),即使这些项目出现在列表中,等等。更简单的ListBox正在按预期工作。

我显然在这里遗漏了一些东西。我可以使用第二种方法,但这真的让我烦恼,我想弄清楚。

作为参考,我的模型是:

public class ProjectEditModel
{
    public Project Project { get; set; }
    public IEnumerable<Project> Projects { get; set; }
    public IEnumerable<Client> Clients { get; set; }
    public IEnumerable<Category> Categories { get; set; }
    public IEnumerable<Tag> Tags { get; set; }
    public ProjectSlide SelectedSlide { get; set; }
}

更新

我刚刚将ListBox名称更改为Project.Categories(匹配我的模型),现在它已选择FAILS来选择项目。

<%= Html.ListBox("Project.Categories",
        new MultiSelectList(Model.Categories, "Id", "Name", new List<int> { 1, 2 }))%>

我显然不理解这里发生的魔法。

更新2

好的,这纯粹是命名,例如,这有效......

<%= Html.ListBox("Project_Tags",
new MultiSelectList(Model.Tags, "Id", "Name", Model.Project.Tags.Select(t => t.Id)))%>

...因为字段名称是Project_Tags,而不是Project.Tags,事实上,除了Tags或Project.Tags之外的任何东西都可以。我不明白为什么这会导致问题(除了它与实体名称相匹配),而且我还不够好,无法挖掘并找到答案。

7 个答案:

答案 0 :(得分:25)

我自己偶然发现了这个问题,最后我意识到这个问题是一个命名约定。

您不能将包含SelectList或MultiSelectList的ViewBag或ViewData属性命名为包含所选项的属性模型的相同名称。至少不是你使用ListBoxFor或DropDownListFor帮助器。

以下是一个例子:

    public class Person
    {
          public List<int> Cars { get; set; }
    }

    [HttpGet]
    public ActionResult Create()
    {
          //wont work
          ViewBag.Cars = new SelectList(carsList, "CarId", "Name"); 

          //will work due to different name than the property.
          ViewBag.CarsList = new SelectList(carsList, "CarId", "Name"); 

          return View();
    }

    //View
    @Html.ListBoxFor(model => model.Cars, ViewBag.CarsList as SelectList)

我确信还有很多其他方法可以做到这一点,但它解决了我的问题,希望它会帮助别人!

答案 1 :(得分:3)

我也遇到了这个完全相同的问题,遇到了与ListBox和ListBoxFor相同的问题。

无论我做什么,我都无法在ListBoxFor上进行选择。如果我更改为ListBox并将其命名为“我绑定的数据的属性名称以外的其他内容”,则会进行选择。

但是因为我没有使用ListBoxFor并且数据位于模型类(Model.Departments)中,例如,我在返回控制器的路上没有得到模型绑定,因此属性为null。

编辑我找到了其他人发布的解决方案; Challenges with selecting values in ListBoxFor

答案 2 :(得分:3)

正确的答案是它不能很好地运作。因此我读了MVC代码。您需要做的是实现IConvertible并创建TypeConverter。

所以,在我的实例中,我有一个Country课程,人们可以从国家列表中进行选择。选择它没有乐趣。我期待一个对象等于selectedItemslistitems的比较,但不是,这不是它的工作原理。尽管MultiListItem工作并正确获取所选项目的事实,但是当它绑定到您的模型时,它都基于检查对象实例的字符串represnetation是否与字符串"value"匹配(或者如果SelectItemList中的项目列表中缺少的内容。

因此,实现IConvertible,返回ToString中与SelectItemList中的值匹配的字符串值。例如,在我的情况下,CountryCode被序列化为SelectItem Value属性,因此在ToString IConvertible我返回了CountryCode。现在一切都正确选择。

我将指出TypeConverter在途中被使用。这次是反过来的。 Countrycode返回,“EN”需要转换为Country类实例。这就是TypeConverter进来的地方。这也是我意识到这种方法难以使用的时候。

p.s所以在您的Category课程中,您需要实施IConvertible。如果它来自作为我公司的实体框架,那么您将需要使用部分类来实现IConvertible并实现ToString并使用您编写的TypeConverter来装饰它。

答案 3 :(得分:2)

此外,您可以尝试在控制器中清除c.Project.Categories的ModelState:

[HttpPost]
public ActionResult Index(ModelType model)
{
    ModelState.Remove("Project.Categories");
    return View("Index", model);
}

使用下一个结构:

<%= Html.ListBoxFor(c => c.Project.Categories,
        new MultiSelectList(Model.Categories, "Id", "Name"))%>

c.Project.Categories为IEnumerable<int>

抱歉我的英文。祝你好运!

答案 4 :(得分:1)

虽然这不是你的主要问题的答案,但值得注意的是,当MVC生成名称时,它会将Project.Tags转换为Project_Tags,用下划线替换句号。

这样做的原因是因为元素ID中的句点看起来像一个名为Project的元素,其中包含一组Tags to CSS。显然是一件坏事,因此转换为下划线以保持行为可预测。

在你的第一个例子中,

<%= Html.ListBoxFor(c => c.Project.Categories,
    new MultiSelectList(Model.Categories, "Id", "Name", new List<int> { 1, 2 }))%>

列表框正在尝试绑定到已提供给页面的强类型模型的Model.Project.Categories(使用lambda表示法)。我不确定ListBoxFor中的第二个参数是做什么的。

传递给页面的模型是什么?

答案 5 :(得分:1)

试试这个

<%= Html.ListBoxFor(c => c.Project.Categories,
    new MultiSelectList(
        Model.Categories
        ,"Id"
        ,"Name"
        ,Model.Project.Tags.Select(
        x => new SelectListItem()
            {
            Selected = true,
            Text = x.TEXT,
            Value = x.ID.ToString()
            }).ToList())

       )
)%>

答案 6 :(得分:1)

当您没有将列表框绑定到其数据源时,Html.ListboxFor和Html.Listbox非常有用。我认为预期的用途是:

// Model
public class ListBoxEditModel
{
    public IEnumerable<Category> Categories { get; set; }
    public IEnumerable<Category> SelectedCategories { get; set; }
}    

在视图中:

@Html.ListBoxFor(m => m.SelectedCategories,
                 new MultiSelectList(Model.Categories, "Id", "Name"))
// or, equivalently
@Html.ListBox("SelectedCategories" ,
                 new MultiSelectList(Model.Categories, "Id", "Name"))

请注意,在这种情况下,您不必明确说明在MultiSelectList中选择了哪些值 - 您绑定的模型优先,即使您这样做!