Zkoumání, jak ASP.NET MVC vygeneruje pomocnou rutinu DropDownList
V Průzkumník řešení klikněte pravým tlačítkem na složku Controllers (Kontrolery) a pak vyberte Add Controller (Přidat kontroler). Pojmenujte řadič StoreManagerController. Nastavte možnosti dialogového okna Přidat kontroler , jak je znázorněno na obrázku níže.
Upravte zobrazení StoreManager\Index.cshtml a odeberte AlbumArtUrl
. Odebráním AlbumArtUrl
bude prezentace čitelnější. Dokončený kód je zobrazený níže.
@model IEnumerable<MvcMusicStore.Models.Album>
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
Genre
</th>
<th>
Artist
</th>
<th>
Title
</th>
<th>
Price
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Genre.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Artist.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id=item.AlbumId }) |
@Html.ActionLink("Details", "Details", new { id=item.AlbumId }) |
@Html.ActionLink("Delete", "Delete", new { id=item.AlbumId })
</td>
</tr>
}
</table>
Otevřete soubor Controllers\StoreManagerController.cs a najděte metodu Index
. Přidejte klauzuli OrderBy
, aby se alba seřadila podle ceny. Kompletní kód je uvedený níže.
public ViewResult Index()
{
var albums = db.Albums.Include(a => a.Genre).Include(a => a.Artist)
.OrderBy(a => a.Price);
return View(albums.ToList());
}
Řazení podle ceny usnadní testování změn v databázi. Při testování metod úprav a vytváření můžete použít nízkou cenu, aby se uložená data zobrazila jako první.
Otevřete soubor StoreManager\Edit.cshtml . Následující řádek přidejte hned za značku legendy.
@Html.HiddenFor(model => model.AlbumId)
Následující kód ukazuje kontext této změny:
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Album</legend>
@Html.HiddenFor(model => model.AlbumId)
<div class="editor-label">
@Html.LabelFor(model => model.GenreId, "Genre")
</div>
<div class="editor-field">
@Html.DropDownList("GenreId", String.Empty)
@Html.ValidationMessageFor(model => model.GenreId)
</div>
<!-- Items removed for brevity. -->
}
Je AlbumId
potřeba k provedení změn záznamu alba.
Stiskněte klávesy CTRL+F5 a spusťte aplikaci. Vyberte odkaz Správa a pak výběrem odkazu Vytvořit nové vytvořte nové album. Ověřte, že se informace o albu uložily. Upravte album a ověřte, že se změny, které jste udělali, zachovaly.
Schéma alba
Kontroler StoreManager
vytvořený mechanismem generování uživatelského rozhraní MVC umožňuje CRUD (Vytvořit, Číst, Aktualizovat, Odstranit) přístup k albům v databázi úložiště hudby. Schéma pro informace o albu je zobrazeno níže:
Tabulka Albums
neukládá žánr a popis alba, ale cizí klíč k Genres
tabulce. Tabulka Genres
obsahuje název a popis žánru. Tabulka také Albums
neobsahuje jméno interpretů alba, ale cizí klíč k tabulce Artists
. Tabulka Artists
obsahuje jméno umělce. Když prozkoumáte data v Albums
tabulce, uvidíte, že každý řádek obsahuje cizí klíč k Genres
tabulce a cizí klíč k Artists
tabulce. Na obrázku níže jsou některá data tabulky z Albums
tabulky.
Značka HTML Select
Element HTML <select>
(vytvořený pomocným pomocníkem HTML DropDownList ) se používá k zobrazení úplného seznamu hodnot (například seznam žánrů). Pokud je u formulářů pro úpravy známá aktuální hodnota, může seznam výběrů zobrazit aktuální hodnotu. Viděli jsme to dříve, když jsme nastavili vybranou hodnotu na Comedy. Seznam výběrů je ideální pro zobrazení dat o kategoriích nebo cizích klíčích. Prvek <select>
cizího klíče Žánr zobrazí seznam možných názvů žánrů, ale když uložíte formulář, vlastnost Žánr se aktualizuje hodnotou cizího klíče Žánr, nikoli zobrazovaným názvem žánru. Na obrázku níže je vybraný žánr Disco a interpretkou je Donna Summer.
Zkoumání ASP.NET kódu vygenerovaného v MVC
Otevřete soubor Controllers\StoreManagerController.cs a najděte metodu HTTP GET Create
.
public ActionResult Create()
{
ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name");
ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name");
return View();
}
Metoda Create
přidá dva SelectList objekty do objektu ViewBag
, jeden obsahuje informace o žánru a druhý k zahrnutí informací o interpretovi. Výše použité přetížení konstruktoru SelectList má tři argumenty:
public SelectList(
IEnumerable items,
string dataValueField,
string dataTextField
)
- items: IEnumerable obsahující položky v seznamu. Ve výše uvedeném příkladu je seznam žánrů vrácených nástrojem
db.Genres
. - dataValueField: Název vlastnosti v seznamu IEnumerable , která obsahuje hodnotu klíče. Ve výše uvedeném příkladu a
GenreId
ArtistId
. - dataTextField: Název vlastnosti v seznamu IEnumerable obsahující informace, které se mají zobrazit. V tabulce interpretů i žánrů se
name
použije pole .
Otevřete soubor Views\StoreManager\Create.cshtml a zkontrolujte Html.DropDownList
pomocné značky pro pole žánru.
@model MvcMusicStore.Models.Album
@* Markup removed for clarity.*@
@Html.DropDownList("GenreId", String.Empty)
První řádek ukazuje, že zobrazení pro vytvoření přebírá Album
model. Create
Ve výše uvedené metodě nebyl předán žádný model, takže zobrazení získá model s hodnotou nullAlbum
. V tuto chvíli vytváříme nové album, takže pro něj nemáme žádná Album
data.
Výše uvedené přetížení Html.DropDownList přebírá název pole, které se má svázat s modelem. Používá také tento název k vyhledání objektu ViewBag obsahujícího SelectList objekt. Při použití tohoto přetížení je nutné pojmenovat objekt GenreId
ViewBag SelectList . Druhý parametr (String.Empty
) je text, který se zobrazí, když není vybrána žádná položka. To je přesně to, co chceme při vytváření nového alba. Pokud jste odebrali druhý parametr a použili následující kód:
@Html.DropDownList("GenreId")
Seznam výběrů by ve výchozím nastavení použil první prvek neboli Horninu v naší ukázce.
Prozkoumání HTTP POST Create
metody
//
// POST: /StoreManager/Create
[HttpPost]
public ActionResult Create(Album album)
{
if (ModelState.IsValid)
{
db.Albums.Add(album);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name",
album.GenreId);
ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name",
album.ArtistId);
return View(album);
}
Toto přetížení Create
metody přebírá album
objekt vytvořený systémem vazby modelu ASP.NET MVC z zaúčtovaných hodnot formuláře. Když odešlete nové album a stav modelu je platný a nedochází k žádným chybám databáze, nové album se přidá do databáze. Následující obrázek znázorňuje vytvoření nového alba.
Nástroj fiddler můžete použít k prozkoumání hodnot zaúčtovaných formulářů, které ASP.NET vazby modelu MVC používají k vytvoření objektu alba.
.
Refaktoring vytvoření viewbag selectList
Edit
Metody i HTTP POST Create
metoda mají stejný kód pro nastavení SelectList v ViewBag. V duchu funkce DRY tento kód refaktorujeme. Tento refaktorovaný kód použijeme později.
Vytvořte novou metodu pro přidání žánru a interpreta SelectList do ViewBag.
private void SetGenreArtistViewBag(int? GenreID = null, int? ArtistID = null) {
if (GenreID == null)
ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name");
else
ViewBag.GenreId = new SelectList(db.Genres.ToArray(), "GenreId", "Name", GenreID);
if (ArtistID == null)
ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name");
else
ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name", ArtistID);
}
Nahraďte dva řádky, které v ViewBag
každé z Create
metod a Edit
nastaví hodnotu , voláním SetGenreArtistViewBag
metody . Dokončený kód je zobrazený níže.
//
// GET: /StoreManager/Create
public ActionResult Create() {
SetGenreArtistViewBag();
return View();
}
//
// POST: /StoreManager/Create
[HttpPost]
public ActionResult Create(Album album) {
if (ModelState.IsValid) {
db.Albums.Add(album);
db.SaveChanges();
return RedirectToAction("Index");
}
SetGenreArtistViewBag(album.GenreId, album.ArtistId);
return View(album);
}
//
// GET: /StoreManager/Edit/5
public ActionResult Edit(int id) {
Album album = db.Albums.Find(id);
SetGenreArtistViewBag(album.GenreId, album.ArtistId);
return View(album);
}
//
// POST: /StoreManager/Edit/5
[HttpPost]
public ActionResult Edit(Album album) {
if (ModelState.IsValid) {
db.Entry(album).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
SetGenreArtistViewBag(album.GenreId, album.ArtistId);
return View(album);
}
Vytvořte nové album a upravte album, abyste ověřili, že změny fungují.
Explicitní předání SelectList do rozevíracího seznamu
Zobrazení pro vytváření a úpravy vytvořená generováním ASP.NET MVC používají následující přetížení DropDownList :
public static MvcHtmlString DropDownList(
this HtmlHelper htmlHelper,
string name, // The name of the ViewModel property to bind.
string optionLabel // The string added to the top of the list
// typically String.Empty or "Select a Genre"
)
Kód DropDownList
pro zobrazení pro vytvoření je zobrazený níže.
@Html.DropDownList("GenreId", String.Empty)
Vzhledem k tomu, že ViewBag
vlastnost objektu SelectList
má název GenreId
, bude pomocná rutina DropDownList používat GenreId
SelectList v oblasti ViewBag. V následujícím přetížení SelectList
DropDownList je explicitně předán.
public static MvcHtmlString DropDownList(
this HtmlHelper htmlHelper,
string name, // The name of the ViewModel property to bind.
IEnumerable selectList // The SelectList
)
Otevřete soubor Views\StoreManager\Edit.cshtml a změňte volání DropDownList tak, aby explicitně předal SelectList s využitím výše uvedeného přetížení. Udělejte to pro kategorii Žánr. Dokončený kód je zobrazený níže:
@Html.DropDownList("GenreId", ViewBag.GenreId as SelectList)
Spusťte aplikaci, klikněte na odkaz Správa, přejděte na album Jazz a vyberte odkaz Upravit.
Místo toho, aby se jako aktuálně vybraný žánr zobrazoval Jazz, se zobrazí Rock. Pokud řetězcový argument (vlastnost pro vazbu) a objekt SelectList mají stejný název, vybraná hodnota se nepoužije. Pokud není zadaná žádná vybraná hodnota, prohlížeč ve výchozím nastavení použije první prvek v SelectList(což je v předchozím příkladu Rock ). Jedná se o známé omezení pomocné rutiny DropDownList .
Otevřete soubor Controllers\StoreManagerController.cs a změňte názvy objektů SelectList na Genres
a Artists
. Dokončený kód je zobrazený níže:
private void SetGenreArtistViewBag(int? GenreID = null, int? ArtistID = null) {
if (GenreID == null)
ViewBag.Genres = new SelectList(db.Genres, "GenreId", "Name");
else
ViewBag.Genres = new SelectList(db.Genres.ToArray(), "GenreId", "Name", GenreID);
if (ArtistID == null)
ViewBag.Artists = new SelectList(db.Artists, "ArtistId", "Name");
else
ViewBag.Artists = new SelectList(db.Artists, "ArtistId", "Name", ArtistID);
}
Názvy Žánry a Umělci jsou lepšími názvy kategorií, protože obsahují více než jen ID každé kategorie. Refaktoring, který jsme provedli dříve, se vyplašil. Místo změny ViewBag ve čtyřech metodách jsme změny izolovali na metodu SetGenreArtistViewBag
.
Změňte volání DropDownList v zobrazení pro vytváření a úpravy tak, aby používalo nové názvy SelectList . Nová značka pro zobrazení pro úpravy je zobrazená níže:
<div class="editor-label">
@Html.LabelFor(model => model.GenreId, "Genre")
</div>
<div class="editor-field">
@Html.DropDownList("GenreId", ViewBag.Genres as SelectList)
@Html.ValidationMessageFor(model => model.GenreId)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.ArtistId, "Artist")
</div>
<div class="editor-field">
@Html.DropDownList("ArtistId", ViewBag.Artists as SelectList)
@Html.ValidationMessageFor(model => model.ArtistId)
</div>
Zobrazení Vytvořit vyžaduje prázdný řetězec, aby se zabránilo zobrazení první položky v seznamu SelectList.
<div class="editor-label">
@Html.LabelFor(model => model.GenreId, "Genre" )
</div>
<div class="editor-field">
@Html.DropDownList("GenreId", ViewBag.Genres as SelectList, String.Empty)
@Html.ValidationMessageFor(model => model.GenreId)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.ArtistId, "Artist")
</div>
<div class="editor-field">
@Html.DropDownList("ArtistId", ViewBag.Artists as SelectList, String.Empty)
@Html.ValidationMessageFor(model => model.ArtistId)
</div>
Vytvořte nové album a upravte album, abyste ověřili, že změny fungují. Otestujte kód pro úpravy výběrem alba s jiným žánrem než Rock.
Použití modelu zobrazení s pomocným nástrojem DropDownList
Ve složce ViewModels vytvořte novou třídu s názvem AlbumSelectListViewModel
. Nahraďte kód ve AlbumSelectListViewModel
třídě následujícím kódem:
using MvcMusicStore.Models;
using System.Web.Mvc;
using System.Collections;
namespace MvcMusicStore.ViewModels {
public class AlbumSelectListViewModel {
public Album Album { get; private set; }
public SelectList Artists { get; private set; }
public SelectList Genres { get; private set; }
public AlbumSelectListViewModel(Album album,
IEnumerable artists,
IEnumerable genres) {
Album = album;
Artists = new SelectList(artists, "ArtistID", "Name", album.ArtistId);
Genres = new SelectList(genres, "GenreID", "Name", album.GenreId);
}
}
}
Konstruktor AlbumSelectListViewModel
vezme album, seznam umělců a žánrů a vytvoří objekt obsahující album a SelectList
pro žánry a umělce.
Sestavte projekt tak, AlbumSelectListViewModel
aby byl k dispozici při vytváření zobrazení v dalším kroku.
Přidejte metodu EditVM
do objektu StoreManagerController
. Dokončený kód je uveden níže.
//
// GET: /StoreManager/EditVM/5
public ActionResult EditVM(int id) {
Album album = db.Albums.Find(id);
if (album == null)
return HttpNotFound();
AlbumSelectListViewModel aslvm = new AlbumSelectListViewModel(album, db.Artists, db.Genres);
return View(aslvm);
}
Klikněte pravým tlačítkem na AlbumSelectListViewModel
, vyberte Vyřešit a pak použijte MvcMusicStore.ViewModels;.
Případně můžete přidat následující příkaz using:
using MvcMusicStore.ViewModels;
Klikněte pravým tlačítkem EditVM
a vyberte Přidat zobrazení. Použijte možnosti uvedené níže.
Vyberte Přidat a pak nahraďte obsah souboru Views\StoreManager\EditVM.cshtml následujícím kódem:
@model MvcMusicStore.ViewModels.AlbumSelectListViewModel
@{
ViewBag.Title = "EditVM";
}
<h2>Edit VM</h2>
@using (Html.BeginForm("Edit","StoreManager",FormMethod.Post)) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Album</legend>
@Html.HiddenFor(model => model.Album.AlbumId )
<div class="editor-label">
@Html.LabelFor(model => model.Album.GenreId, "Genre")
</div>
<div class="editor-field">
@Html.DropDownList("Album.GenreId", Model.Genres)
@Html.ValidationMessageFor(model => model.Album.GenreId)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Album.ArtistId, "Artist")
</div>
<div class="editor-field">
@Html.DropDownList("Album.ArtistId", Model.Artists)
@Html.ValidationMessageFor(model => model.Album.ArtistId)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Album.Title)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Album.Title)
@Html.ValidationMessageFor(model => model.Album.Title)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Album.Price)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Album.Price)
@Html.ValidationMessageFor(model => model.Album.Price)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Album.AlbumArtUrl)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Album.AlbumArtUrl)
@Html.ValidationMessageFor(model => model.Album.AlbumArtUrl)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
Kód EditVM
je velmi podobný původnímu Edit
kódu s následujícími výjimkami.
- Vlastnosti modelu v
Edit
zobrazení jsou ve formátumodel.property
(napříkladmodel.Title
). Vlastnosti modelu vEditVm
zobrazení jsou ve formátumodel.Album.property
(napříkladmodel.Album.Title
). Je to proto, žeEditVM
zobrazení je předáno kontejneruAlbum
pro , ne jakoAlbum
vEdit
zobrazení. - Druhý parametr DropDownList pochází z modelu zobrazení, nikoli z ViewBag.
- Pomocník BeginForm v
EditVM
zobrazení explicitně odešle zpět doEdit
metody akce. Odesláním zpět doEdit
akce nemusíme napsatHTTP POST EditVM
akci a můžeme akci znovu použítHTTP POST
Edit
.
Spusťte aplikaci a upravte album. Změňte adresu URL tak, aby používala EditVM
. Změňte pole a stisknutím tlačítka Uložit ověřte, že kód funguje.
Jaký přístup byste měli použít?
Všechny tři uvedené přístupy jsou přijatelné. Mnoho vývojářů dává přednost explicitně předat SelectList
nástroji DropDownList
pomocí ViewBag
. Tento přístup má další výhodu v tom, že poskytuje flexibilitu používání vhodnějšího názvu kolekce. Jediným upozorněním je, že objekt nemůžete pojmenovat ViewBag SelectList
stejným názvem jako vlastnost modelu.
Někteří vývojáři dávají přednost přístupu ViewModel. Jiní považují podrobnější značky a vygenerované HTML přístupu ViewModel za nevýhodu.
V této části jsme se seznámili se třemi přístupy k použití rozevíracího seznamu s daty kategorií. V další části si ukážeme, jak přidat novou kategorii.
Váš názor
https://aka.ms/ContentUserFeedback.
Připravujeme: V průběhu roku 2024 budeme postupně vyřazovat problémy z GitHub coby mechanismus zpětné vazby pro obsah a nahrazovat ho novým systémem zpětné vazby. Další informace naleznete v tématu:Odeslat a zobrazit názory pro