ASP.NET核心 - MVC。下拉填充问题

时间:2017-11-13 15:41:59

标签: asp.net-mvc

我正在使用vs 2017和chrome。

我有一个ASP.Net核心MVC应用程序。它有一个下拉列表,没有正确显示项目。显示的项目应为:喜剧,西方和浪漫。

enter image description here

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

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

enter image description here

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

enter image description here

我填充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;
    }

以下是观点:

&#13;
&#13;
@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>
&#13;
&#13;
&#13;

本教程使用的是Entity Framework,但我将其转换为使用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);
    }

enter image description here

enter image description here

2 个答案:

答案 0 :(得分:0)

从屏幕截图中可以清楚地看出,SelectListDataTextField错过了DataValueField。所以SELECT标记帮助器不知道哪个属性应该用于文本,哪个属性应该用于Value。

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

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

现在,在您的视图中,您可以将Select tag helper与此genres属性

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

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

由于您的enter code here Genre类中只有一个属性,因此您可以将字符串列表传递给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

答案 1 :(得分:0)

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

        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属性。属性可以是您想要的名称。在这种情况下&#34; item&#34;有这些属性。