选择标签助手以在下拉列表中显示2个字段

时间:2019-04-11 11:36:46

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

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

我已尝试使用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一起使用。

2 个答案:

答案 0 :(得分: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();

答案 1 :(得分:0)

我遵循了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