【问题标题】:Select Tag Helper to Display 2 Fields in the Drop Down List选择 Tag Helper 以在下拉列表中显示 2 个字段
【发布时间】:2019-04-11 11:36:46
【问题描述】:

使用标准脚手架仅在相关表的下拉列表中显示索引。如何显示多个字段,让下拉列表有意义?

我尝试使用 Shyju 在“使用实体框架从数据库表中获取数据”部分中概述的解决方案。 (Select Tag Helper in ASP.NET Core MVC)。

我在模型中有 2 个类(具有相关作者的书籍):

namespace SimpleAppwithTwoTables.Data
{
    public class Book
    {
        public int BookID { get; set; }
        [StringLength(255)]
        [Display(Name ="Book Title")]
        public string Title { get; set; }
        public int AuthorID { get; set; }
        public Author Author { get; set; }
     }
}

和

namespace SimpleAppwithTwoTables.Data
{
    public class Author
    {
        public int AuthorID { get; set; }
        [Display(Name = "First Name")]
        [StringLength(50)]
        public string FirstName { get; set; }
        [Display(Name = "Last Name")]
        [StringLength(50)]
        public string LastName { get; set; }
        public ICollection<Book> Books { get; set; } = new List<Book>();
    }
}

BooksController 有一个 Create() 方法,类似于 Shyju 的帖子中描述的方法。

 public IActionResult Create()
            Author vm = new Author();
            vm.Books = _context.Book.Select(a => new SelectListItem()
            { Value = a.AuthorID.ToString(), Text = a.Author.LastName }).ToList();
            return View(vm);
        }

控制器中的这一行

 vm.Books = _context.Book.Select(a => new SelectListItem()
            { Value = a.AuthorID.ToString(), Text = a.Author.LastName }).ToList();

产生这个错误:

"不能隐式转换类型 'System.Collections.Generic.List' 到 'System.Collections.Generic.ICollection'。 存在显式转换(您是否缺少演员表?)。

请注意,我是 C# 新手,并且了解这是一个类型转换问题,并且出现错误的行预期 Author 模型包含 ICollection。

我正在 vm.books 行中寻找不进行类型转换并与 ICollection 一起使用的代码。

【问题讨论】:

    标签: c# asp.net-core asp.net-core-mvc entity-framework-core


    【解决方案1】:

    您正在尝试将SelectListItem 列表填充到定义为Book 列表的属性中。 SelectListItem 显然和Book 不一样,所以它失败了。

    简单的解决方案是您的视图模型上需要一个属性,专门用于保存您的选择列表选项:

    public IEnumerable<SelectListItem> AuthorOptions { get; set; }
    

    您还需要一些东西来将选择项绑定到,这将是原始类型,而不是实际的 Author 实例:

    public List<int> SelectedAuthorIds { get; set; }
    

    在你看来,那么:

    <select asp-for="SelectedAuthorIds" asp-items="AuthorOptions">
    

    在发布时,如果您需要将它们与一本书或其他东西相关联,您将需要使用该 ID 集合来查询实际的作者对象:

    var selectAuthors = await _context.Authors.Where(x => vm.SelectedAuthorIds.Contains(x.Id)).ToListAsync();
    

    【讨论】:

    • 克里斯,嗨。感谢您的反馈。看起来很简单,但我无法锻炼如何将其连接起来以使用数据模型。非常感谢。
    【解决方案2】:

    我遵循了 Chris Pratt 上面提供的建议。花了一段时间才弄清楚,但几乎可以工作了。请参阅下面的详细信息。

    参见上面的书籍和作者模型。

    创建了一个新的 ViewModel:

    namespace SimpleDropDownList.Models
    {
        [NotMapped]
        public class AuthorViewModel
        {
            //Property to hold the list of authors in the GET
            public IEnumerable<SelectListItem> AuthorOptions { get; set; }
    
            //Property to bind the selected author used in the POST
            public List<int> SelectedAuthorIds { get; set; }
        }
    }
    

    将 BooksController 上的 Create() 方法更改为:

     public IActionResult Create()
            {
                //ViewData["AuthorID"] = new SelectList(_context.Set<Author>(), "AuthorID", "AuthorID");
                AuthorViewModel vm = new AuthorViewModel();
                vm.AuthorOptions = _context.Book.Select(x => new SelectListItem()
                { Value = x.AuthorID.ToString(), Text = x.Author.LastName }).ToList();
            return View(vm);
            }
    

    将创建视图更改为:

    @model SimpleDropDownList.Models.Book
    
    @{
        ViewData["Title"] = "Create";
    }
    
    <h1>Create</h1>
    
    <h4>Book</h4>
    <hr />
    <div class="row">
        <div class="col-md-4">
            <form asp-action="Create">
                <div asp-validation-summary="ModelOnly" class="text-danger"></div>
                <div class="form-group">
                    <label asp-for="Title" class="control-label"></label>
                    <input asp-for="Title" class="form-control" />
                    <span asp-validation-for="Title" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="AuthorID" class="control-label"></label>
                    @*<select asp-for="AuthorID" class ="form-control" asp-items="ViewBag.AuthorID"></select>*@
    
                    <select asp-for="@Model.AuthorViewModel.SelectedAuthorIds" asp-items="@Model.AuthorViewModel.AuthorOptions"></select>
                    
                </div>
                <div class="form-group">
                    <input type="submit" value="Create" class="btn btn-primary" />
                </div>
            </form>
        </div>
    </div>
    
    <div>
        <a asp-action="Index">Back to List</a>
    </div>
    
    @section Scripts {
        @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    }
    Model: AuthorViewModel

    当我运行它并单击创建按钮时,会生成以下错误:

    处理请求时发生未处理的异常。 InvalidOperationException:传入的模型项 ViewDataDictionary 是类型 'SimpleDropDownList.Models.AuthorViewModel',但这 ViewDataDictionary 实例需要类型为模型项 'SimpleDropDownList.Models.Book'。

    我将此问题标记为已完成,并针对上述问题创建了一个新问题。见这里:Error when Razor page opens and have a related drop down list

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-17
      • 1970-01-01
      • 1970-01-01
      • 2017-03-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多