Sdílet prostřednictvím


Zkoumání, jak ASP.NET MVC vygeneruje uživatelské rozhraní pomocné rutiny DropDownList

Rick Anderson

V Průzkumník řešení klikněte pravým tlačítkem myši na složku Kontrolery a pak vyberte 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.

Obrázek dialogového okna přidat kontroler Průzkumník řešení

Upravte zobrazení StoreManager\Index.cshtml a odeberte AlbumArtUrl. Odebráním AlbumArtUrl bude prezentace čitelnější. Dokončený kód je uvedený 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 vyhledejte metoduIndex. Přidejte klauzuli OrderBy , aby alba byla seřazena 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 zobrazovala jako první.

Otevřete soubor StoreManager\Edit.cshtml. Přidejte následující řádek těsně 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 nutné provést změny v záznamu alba.

Stiskněte klávesy CTRL+F5 a spusťte aplikaci. Vyberte odkaz Správce a pak výběrem odkazu Vytvořit nový vytvořte nové album. Ověřte, že byly uloženy informace o albu. Upravte album a ověřte, že provedené změny jsou trvalé.

Schéma alba

StoreManager Kontroler vytvořený mechanismem generování uživatelského rozhraní MVC umožňuje CRUD (Create, Read, Update, Delete) přístup k albům v databázi úložiště hudby. Schéma informací o albu je znázorněno níže:

Obrázek schématu Alba

Tabulka Albums neukládá žánr a popis alba, ukládá cizí klíč do Genres tabulky. Tabulka Genres obsahuje název a popis žánru. Albums Stejně tak tabulka neobsahuje název umělce alba, ale cizí klíč tabulkyArtists. Tabulka Artists obsahuje jméno autora. Pokud prozkoumáte data v Albums tabulce, můžete vidět, že každý řádek obsahuje cizí klíč tabulky Genres a cizí klíč tabulky Artists . Na následujícím obrázku jsou některá data tabulky z Albums tabulky.

Obrázek některých dat z tabulky Alba

Značka Pro výběr HTML

Element HTML <select> (vytvořený pomocným rutinou HTML DropDownList ) slouží k zobrazení kompletního seznamu hodnot (například seznam žánrů). Při úpravách formulářů, pokud je aktuální hodnota známá, může seznam výběru 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 kategorie nebo cizího klíče. Prvek <select> cizího klíče Žánr zobrazuje seznam možných názvů žánrů, ale když uložíte formulář Žánr vlastnost se aktualizuje hodnotou cizího klíče Žánr, nikoli zobrazovaný název žánru. Na obrázku níže je žánr vybraný Disko a umělec je Donna Summer.

Obrázek vybraného žánru Disko

Prozkoumání kódu vygenerovaného uživatelského rozhraní MVC ASP.NET

Otevřete soubor Controllers\StoreManagerController.cs a vyhledejte metoduHTTP 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 ViewBag, jeden obsahovat informace o žánru, a jeden, který bude obsahovat informace interpreta. Přetížení konstruktoru SelectList použité výše přebírá tři argumenty:

public SelectList(

    IEnumerable items,

    string dataValueField,

    string dataTextField

)
  1. items: IEnumerable obsahující položky v seznamu. V předchozím příkladu seznam žánrů vrácených db.Genres.
  2. dataValueField: Název vlastnosti v seznamu IEnumerable , který obsahuje hodnotu klíče. V příkladu výše GenreId a ArtistId.
  3. dataTextField: Název vlastnosti v seznamu IEnumerable , který obsahuje informace k zobrazení. V tabulce umělců i žánrů se name pole používá.

Otevřete soubor Views\StoreManager\Create.cshtml a prozkoumejte 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í používá 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.

Přetížení Html.DropDownList zobrazené výše přebírá název pole, které se má svázat s modelem. Tento název také používá k vyhledání objektu ViewBag obsahující objekt SelectList . Pomocí tohoto přetížení je nutné pojmenovat ViewBag SelectList objekt GenreId. Druhý parametr (String.Empty) je text, který se má zobrazit, 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")

Výběrový seznam by ve výchozím nastavení byl první prvek nebo Rock v naší ukázce.

Obrázek výchozího prvního prvku

HTTP POST Create Zkoumání 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 publikovaných hodnot formuláře. Když odešlete nové album, pokud je stav modelu platný a nedojde k žádným chybám databáze, přidá se nové album do databáze. Následující obrázek znázorňuje vytvoření nového alba.

Obrázek znázorňující vytvoření nového alba

Nástroj fiddler můžete použít k prozkoumání odeslaných hodnot formuláře, které ASP.NET vazby modelu MVC používá k vytvoření objektu alba.

Obrázek nástroje Fiddler.

Refaktoring vytvoření selectlistu ViewBag

Metody Edit i HTTP POST Create metoda mají identický kód pro nastavení SelectList v ViewBag. V duchu DRY budeme refaktorovat tento kód. 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é nastaví ViewBag v jednotlivých metodách Create Edit , voláním SetGenreArtistViewBag metody. Dokončený kód je uvedený 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í seznamu SelectList do rozevíracího seznamu

Při vytváření a úpravách zobrazení vytvořených generováním ASP.NET MVC se používá 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 uvedený níže.

@Html.DropDownList("GenreId", String.Empty)

ViewBag Protože vlastnost pro název SelectList GenreId, DropDownList pomocník bude používatGenreId SelectList v ViewBag. V následujícím dropDownList přetížení je SelectList 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 explicitně předat SelectList pomocí přetížení výše. Udělejte to pro kategorii Žánr. Dokončený kód je uvedený níže:

@Html.DropDownList("GenreId", ViewBag.GenreId as SelectList)

Spusťte aplikaci a klikněte na odkaz Správce , přejděte do alba Jazz a vyberte odkaz Upravit .

Obrázek výběru alba Jazz pro úpravy

Místo zobrazení Jazzu jako aktuálně vybraného žánru se zobrazí Rock. Pokud řetězcový argument (vlastnost vytvořit vazbu) a selectList objekt mají stejný název, vybraná hodnota se nepoužije. Pokud není k dispozici žádná vybraná hodnota, prohlížeče ve výchozím nastavení první prvek v SelectList(což je Rock v příkladu výše). Toto je 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 uvedený 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 udělali dříve, se vyplatil. Místo změny ViewBagu ve čtyřech metodách byly naše změny izolované pro metoduSetGenreArtistViewBag.

Změňte volání DropDownList v zobrazení pro vytvoření a úpravu tak, aby používaly nové názvy SelectList. Nový kód 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 úprav tak, že vyberete album s jiným žánrem než Rock.

Použití modelu zobrazení s pomocným nástrojem DropDownList

Vytvořte novou třídu ve složce ViewModels 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 žánry a umělce.

Sestavte projekt tak, aby AlbumSelectListViewModel 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 myši , vyberte Přeložit a pak použijte MvcMusicStore.ViewModels;.AlbumSelectListViewModel

Obrázek s výběrem překladu

Alternativně můžete přidat následující příkaz using:

using MvcMusicStore.ViewModels;

Klikněte pravým tlačítkem myši EditVM a vyberte Přidat zobrazení. Použijte níže uvedené možnosti.

Obrázek s dialogovým oknem Přidat zobrazení

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 formuláři model.property(například model.Title ). Vlastnosti modelu v EditVm zobrazení jsou ve formuláři model.Album.property(například model.Album.Title). Je to proto, že EditVM zobrazení se předává kontejneru pro objekt Album, nikoli jako Album v Edit zobrazení.
  • Druhý parametr DropDownList pochází z modelu zobrazení, nikoli ViewBag.
  • Pomocná rutina BeginForm v EditVM zobrazení explicitně publikuje zpět do Edit metody akce. Odesláním zpět na Edit akci nemusíme napsat HTTP POST EditVM akci a akci znovu použít HTTP 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.

Image with U R L change to Edit V M

Jaký přístup byste měli použít?

Všechny tři zobrazené přístupy jsou přijatelné. Mnoho vývojářů dává přednost tomu, aby explicitně předalo SelectList DropDownList použití ViewBag. Díky tomuto přístupu získáte větší flexibilitu při používání vhodnějšího názvu kolekce. Jedním upozorněním je, že objekt nemůže pojmenovat ViewBag SelectList stejný název jako vlastnost modelu.

Někteří vývojáři dávají přednost přístupu ViewModel. Ostatní považují za nevýhodu více podrobných značek a vygenerovaný kód HTML modelu ViewModel.

V této části jsme se naučili tři přístupy k používání rozevíracího seznamu s daty kategorií. V další části si ukážeme, jak přidat novou kategorii.