首页 文章

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

提问于
浏览
29

我在视图中有以下代码:

<%= 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)和 it fails to show the selected items (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 回答

  • 3

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

    您不能将包含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

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

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

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

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

  • 1

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

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

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

    我会指出 TypeConverter 是在途中使用的 . 这次是反过来的 . 那 Countrycode 重新进入并且"EN"需要转换为 Country 类实例 . 这就是 TypeConverter 进来的地方 . 这也是我意识到这种方法难以使用的时候 .

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

  • 1

    此外,您可以尝试在控制器中清除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> .

    对不起我的英语不好 . 祝好运!

  • 3

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

    这样做的原因是因为元素ID中的句点看起来像一个名为Project的元素,其中包含一组标签到CSS . 显然是一件坏事,因此转换为强调以保持行为可预测 .

    在你的第一个例子中,

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

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

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

  • 2

    试试这个

    <%= 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())
    
           )
    )%>
    
  • 25

    当您没有将列表框绑定到其数据源时,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中选择了哪些值 - 您绑定的模型优先,甚至如果你这样做!

相关问题