【问题标题】:ASP.NET Core - MVC. Drop down populate issueASP.NET 核心 - MVC。下拉填充问题
【发布时间】:2017-11-14 01:21:55
【问题描述】:

我正在使用 vs 2017 和 chrome。

我有一个 ASP.Net Core MVC 应用程序。它有一个未正确显示项目的下拉菜单。显示的项目应该是:喜剧、西部和浪漫。

这是调试图像。这些项目显示了数组和文本 {MvcMovie.Modesl.Genre},当我单击每个项目时,项目文本显示为我想要的。

我从数据库中选择流派并将它们作为 List 返回并将其转换为 SelectList,因为这就是它呈现为 HTML 的元素,它是具有 SelectListItem 对象集合的元素。

但是,当我查看原始视图时,我只看到文本 {MvcMovie.Modesl.Genre},这就是下拉菜单中显示的内容。

我填充了 movieGenreVM 并将其作为视图返回到 Index 操作方法中。

      public IActionResult Index(string movieGenre, string searchStringEntered)
    {
        // A list of genre objects.
        SelectList genresList;

        // A list of movie objects.
        List<Movie> moviesList;

        // Instantiate the View model.
        var movieGenreVM = new MovieGenreViewModel();

        // Get a list of genres from the database.
        genresList = new SelectList(GetGenres(movieGenre));

        // Get a list of movies from the database.
        moviesList = GetMovies(searchStringEntered);

        // Sets the models property which is then used in the dropdown of Genres.
        movieGenreVM.genres = genresList;

        // Creates a List object.
        // Movie is populated from the database and used to generate an HTML table of loaded movies.
        movieGenreVM.movies = moviesList;

        // Passing the MovieGenreViewModel.
        // Return the IActionResult - the Index.cshtml. A view template to generate an HTML response to the browser.
        return View(movieGenreVM);
    }


namespace MvcMovie.Models
{
public class MovieGenreViewModel
{
    // A list of movies.
    public List<Movie> movies;

    // A SelectList containing the list of genres. 
    public SelectList genres;

    // Contains the selected genre.
    public string movieGenre { get; set; }
  }
}

流派模型是:

public class Genre
{
    public string MovieGenre { get; set; }

    // Constructor.
    public Genre()
    {
    }

    public Genre(string a_MovieGenre)
    {
        MovieGenre = a_MovieGenre;
    }
}

这是类型列表代码的人口:

    // Create a list of genres.
    private List<Genre> _genre = new List<Genre>();

    public List<Genre> Genre
    {
        get
        {
            return _genre;
        }
    }

    public List<Genre> GetGenres(string movieGenre)
    {
        Boolean errorSw = false;

        // Declare the reader and initialize.
        SqlDataReader GenresDataReader = null;

        try
        {
            // Open the connection.
            dbFunc.OpenDB();

            // Get the list of distinct Genres by executing a stored procedure.
            SqlCommand GenresCmd = new SqlCommand("dbo.SelectGenres", dbFunc.objConn);
            GenresCmd.Parameters.Clear();
            GenresCmd.CommandType = CommandType.StoredProcedure;
            GenresCmd.Parameters.Add("@SearchText", SqlDbType.VarChar).Value = movieGenre;

            // Set the reader.
            GenresDataReader = GenresCmd.ExecuteReader();

            // Loop thru the results returned.
            while (GenresDataReader.Read())
            {
                // Add to the list of genres - creates a new row for the collection.
                Genre.Add(new Genre(GenresDataReader["Genre"].ToString()));
            }
        }
        catch (Exception ex)
        {
            errorSw = true;
        }
        finally
        {
            if (GenresDataReader != null)
            {
                GenresDataReader.Close();
            }

            dbFunc.CloseDB();
        }

        // Return the list of genre objects.
        return Genre;
    }

这是视图:

@model MvcMovie.Models.MovieGenreViewModel

@{
    ViewData["Title"] = "Index";
}

<h2>List of Movies</h2>

<p>
    <a asp-action="Create">Create New</a>
</p>

<form asp-controller="Movies" asp-action="Index" method="get">
    <p>
        @* A dropdown. *@
        <select asp-for="movieGenre" asp-items="Model.genres">
            <option value="">All</option>
        </select>

        Title: <input type="text" name="searchStringEntered">

        <input type="submit" value="Filter" />
    </p>
</form>

@* Shows the list of movies. *@
<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.movies[0].Title)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.movies[0].ReleaseDate)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.movies[0].Genre)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.movies[0].Price)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.movies[0].Rating)
            </th>
            <th></th>
        </tr>
    </thead>

    <tbody>
        @foreach (var item in Model.movies) {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.Title)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.ReleaseDate)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Genre)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Price)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Rating)
                </td>
                <td>                        
                    <a asp-action="Edit" asp-route-id="@item.ID">Edit</a> |
                    <a asp-action="Details" asp-route-id="@item.ID">Details</a> |
                    <a asp-action="Delete" asp-route-id="@item.ID">Delete</a>
                </td>
            </tr>
         }
    </tbody>
</table>

本教程使用实体框架,但我将其转换为使用 ADO.net 和存储过程。 EF 版本的下拉菜单运行良好。

这里是 EF 版本索引操作方法。类型只是文本 - 没有与之关联的 Id。

    public async Task<IActionResult> Index(string movieGenre, string searchStringEntered)
    {
        IQueryable<string> genreQuery = from m in _context.Movie
                                        orderby m.Genre
                                        select m.Genre;

        var movies = from m in _context.Movie
                     select m;

        if (!String.IsNullOrEmpty(searchStringEntered))
        {
            movies = movies.Where(s => s.Title.Contains(searchStringEntered));
        }

        if (!String.IsNullOrEmpty(movieGenre))
        {
            movies = movies.Where(x => x.Genre == movieGenre);
        }

        // Instantiate the model.
        var movieGenreVM = new MovieGenreViewModel();

        // The SelectList of genres is created by projecting the distinct genres.
        // Sets the models property which is then used in the dropdown of Genres.
        movieGenreVM.genres = new SelectList(await genreQuery.Distinct().ToListAsync());

        // Creates a List object.
        // Movie is populated from the database and used to generate an HTML table of loaded movies.
        movieGenreVM.movies = await movies.ToListAsync();

        return View(movieGenreVM);
    }

【问题讨论】:

  • 请显示 SelectList 的数量以及 html 视图
  • 渲染 SELECT 元素的代码在哪里? GetGenres 方法的返回类型是什么?邮政编码,不是图片
  • 好的...我已经添加了它们。

标签: asp.net-mvc


【解决方案1】:

从您的屏幕截图中,很明显您的SelectList 缺少DataTextFieldDataValueField。所以 SELECT 标签助手不知道哪个属性应该用于文本,哪个属性应该用于值。

解决方案是在创建 SelectList 对象时指定它。由于您的Genre 实体类只有一个属性MovieGenre,因此您可以将其用于 Text 和 Value

var generesList = new SelectList(GetGenres(movieGenre),"MovieGenre","MovieGenre");
var vm=new MovieGenreViewModel { genres= generesList};
return View(vm);

现在在您看来,您可以将 Select 标签助手与 genres 属性一起使用

@model MovieGenreViewModel
<select asp-for="movieGenre" asp-items="@Model.genres"></select>

选择标签助手将使用DataValueField 属性值作为选项值属性,使用DataTextField 属性值作为选项文本。

或者由于您的enter code hereGenre 类中只有一个属性,您可以将字符串列表传递给SelectList 构造函数。下面的也可以。

var gList=GetGenres(movieGenre);
var generesList = new SelectList(gList.Select(a=>a.MovieGenre));
var vm=new MovieGenreViewModel { genres= generesList};
return View(vm);

这里有一篇文章解释了使用 SELECT 标签助手的不同选项,供您参考

Select Tag Helper in ASP.NET Core MVC

【讨论】:

  • 我明白你在说什么,但是通过从电影表中选择不同的流派文本列来生成流派(通过存储过程)。所以没有“价值”(键)——只有“喜剧”之类的文本。这是一个使用实体框架开发的教程,我正在将其转换为 ADO.net。(我没有改变视图)EF应用程序的版本,并且没有“价值”(键)——只有诸如“喜剧”之类的文本。我将包含 EF 代码进行比较。
  • 是的。您可以传递字符串列表,也可以将 MovieGenre 属性指定为值和文本。查看更新的答案。
  • 好的..但是在上面显示的 EF 版本中 - 有效,为什么我不必做你建议的任何事情?
  • 因为您的 linq 表达式 genreQuery 正在选择 Genre 属性。所以基本上await genreQuery.Distinct().ToListAsync() 将生成一个字符串列表(对于每个不同的流派名称),并且您将该列表传递给 SelectList 构造函数,并且选择列表将使用该列表来呈现选项。这里每个项目(字符串)都将用作选项的文本。在您之前的案例中,它是您尝试传递的 Genre 类对象的列表。如果您对 MovieGenre 属性名称进行选择,它将起作用 (new SelectList(GetGenres.Select(a=&gt;a.MovieGenre));
【解决方案2】:

这是我如何做的一个例子:

        var items = GetItemsFromDB();
        var vals = new List<SelectListItem> {new SelectListItem {Selected = true, Text = "--Select an Item--", Value = "0"}};

        vals.AddRange(items.Select(item => new SelectListItem
        {
            Selected = false, Text = item.Type, Value = item.Id.ToString()
        }));

        var result = new SelectList(vals, "Value", "Text");

正如您所见,当我将其转换为 SelectList 时,我将 Value 和 Text 指定为 dataValueField 和 dataTextField。

在您的情况下,您需要这些值的属性,并在使用 SelectList 构造函数“强制转换”时指定它们。

在我看来,我这样做:

<select asp-for="Model.ItemId" asp-items="Model.MyItemSelectList"></select>

Model.MyItemSelectList 可以是 SelectListItem 的列表

将它绑定到集合的另一种方法是这样的:

                                     <select asp-for="Model.MyItemId">
                                        <option value="">-- Select Item --</option>
                                        @{                                                
                                             foreach (var item in Model.MyItems)
                                             {
                                                 <option value="@item.Key">@item.Value</option>
                                             }                                                
                                        }
                                    </select>

其中 item 具有 Key 和 Value 属性。属性可以是任何你想要的名称。在这种情况下,“item”具有这些属性。

【讨论】:

  • 我明白你在说什么,但是通过从电影表中选择不同的流派文本列来生成流派(通过存储过程)。所以没有“价值”(键)——只有诸如“喜剧”之类的文本。这是一个使用实体框架开发的教程,我正在将其转换为 ADO.net(我没有更改视图)。EF应用程序的版本并且没有“价值”(键) - 只有“喜剧”之类的文本,它工作正常。我将包含上面的 EF 代码进行比较。
  • 流派是如何生成的并不重要。例如,只要属性是唯一的,您就可以对值和文本使用相同的属性。因此,如果流派是独一无二的,您仍然可以使用它们。
猜你喜欢
  • 1970-01-01
  • 2014-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多