Aracılığıyla paylaş


ASP.NET MVC tarafından DropDownList yardımcısı için nasıl iskele oluşturulduğunu inceleme

tarafından Rick Anderson

Çözüm Gezgini'da Denetleyiciler klasörüne sağ tıklayın ve ardından Denetleyici Ekle'yi seçin. Denetleyiciye StoreManagerController adını verin. Aşağıdaki resimde gösterildiği gibi Denetleyici Ekle iletişim kutusunun seçeneklerini ayarlayın.

Çözüm Gezgini Denetleyici Ekle iletişim kutusunun resmi

StoreManager\Index.cshtml görünümünü düzenleyin ve kaldırınAlbumArtUrl. Kaldırma işlemi AlbumArtUrl sunuyu daha okunabilir hale getirir. Tamamlanmış kod aşağıda gösterilmiştir.

@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>

Controllers\StoreManagerController.cs dosyasını açın ve yöntemini bulunIndex. Albümlerin OrderBy fiyata göre sıralanması için yan tümcesini ekleyin. Kodun tamamı aşağıda gösterilmiştir.

public ViewResult Index()
{

    var albums = db.Albums.Include(a => a.Genre).Include(a => a.Artist)

        .OrderBy(a => a.Price);

    return View(albums.ToList());

}

Fiyata göre sıralamak, veritabanındaki değişiklikleri test etme işlemini kolaylaştırır. Düzenleme ve oluşturma yöntemlerini test ederken, kaydedilen verilerin önce görünmesi için düşük bir fiyat kullanabilirsiniz.

StoreManager\Edit.cshtml dosyasını açın. Gösterge etiketinin hemen arkasına aşağıdaki satırı ekleyin.

@Html.HiddenFor(model => model.AlbumId)

Aşağıdaki kod bu değişikliğin bağlamını gösterir:

@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. -->

}

AlbumId bir albüm kaydında değişiklik yapmak için gereklidir.

Uygulamayı çalıştırmak için CTRL+F5'e basın. Yönetici bağlantısına gidin ve ardından Yeni Oluştur bağlantısını seçerek yeni bir albüm oluşturun. Albüm bilgilerinin kaydedildiği doğrulayın. Bir albümü düzenleyin ve yaptığınız değişikliklerin kalıcı olduğunu doğrulayın.

Albüm Şeması

StoreManager MVC iskele mekanizması tarafından oluşturulan denetleyici, CRUD'nin (Oluşturma, Okuma, Güncelleştirme, Silme) müzik deposu veritabanındaki albümlere erişmesine izin verir. Albüm bilgileri şeması aşağıda gösterilmiştir:

Albüm şemasının görüntüsü

Tablo albüm Albums türünü ve açıklamasını depolamaz, tablonun yabancı anahtarını Genres depolar. Genres Tabloda tür adı ve açıklaması yer alır. Benzer şekilde, Albums tabloda albüm sanatçılarının adı değil, tablonun yabancı anahtarı Artists yer alır. Tabloda Artists sanatçının adı yer alır. Tablodaki verileri incelerseniz, her satırın Albums tablo için Genres bir yabancı anahtar ve tabloya yabancı anahtar içerdiğini Artists görebilirsiniz. Aşağıdaki resimde tablodan bazı tablo verileri gösterilmektedir Albums .

Albümler tablosundaki bazı verilerin görüntüsü

HTML Select Etiketi

HTML <select> öğesi (HTML DropDownList yardımcısı tarafından oluşturulan), değerlerin tam listesini (tür listesi gibi) görüntülemek için kullanılır. Düzenleme formları için, geçerli değer bilindiğinde, seçme listesi geçerli değeri görüntüleyebilir. Bunu daha önce, seçilen değeri Comedy olarak ayarladığımızda görmüştük. Seçme listesi, kategori veya yabancı anahtar verilerini görüntülemek için idealdir. <select> Genre yabancı anahtarının öğesi olası tür adlarının listesini görüntüler, ancak formu kaydettiğinizde Tarz özelliği görüntülenen tür adıyla değil, Tarz yabancı anahtar değeriyle güncelleştirilir. Aşağıdaki resimde, seçilen tarz Disco, sanatçı ise Donna Summer' dır.

Disko'nun seçili türünün görüntüsü

ASP.NET MVC yapı iskelesi kodunu inceleme

Controllers\StoreManagerController.cs dosyasını açın ve yöntemini bulunHTTP GET Create.

public ActionResult Create()

{

    ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name");

    ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name");

    return View();

}

yöntemi, Create biri tarz bilgilerini, biri de sanatçı bilgilerini içerecek şekilde öğesine iki SelectList nesnesi ViewBagekler. Yukarıda kullanılan SelectList oluşturucu aşırı yüklemesi üç bağımsız değişken alır:

public SelectList(

    IEnumerable items,

    string dataValueField,

    string dataTextField

)
  1. items: Listedeki öğeleri içeren bir IEnumerable . Yukarıdaki örnekte, tarafından db.Genresdöndürülen türlerin listesi.
  2. dataValueField: Anahtar değerini içeren IEnumerable listesindeki özelliğin adı. Yukarıdaki GenreId örnekte ve ArtistId.
  3. dataTextField: Görüntülenecek bilgileri içeren IEnumerable listesindeki özelliğin adı. Hem sanatçılar hem de tarz tablosunda name alan kullanılır.

Views\StoreManager\Create.cshtml dosyasını açın ve tür alanının yardımcı işaretlemesini inceleyinHtml.DropDownList.

@model MvcMusicStore.Models.Album

@*        Markup removed for clarity.*@

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

İlk satır, oluşturma görünümünün bir Album model aldığını gösterir. Yukarıda gösterilen yöntemde Create hiçbir model geçirilmiyor, bu nedenle görünüm null Album model alıyor. Bu noktada yeni bir albüm oluşturuyoruz, bu nedenle bu albümle ilgili hiçbir Album verimiz yok.

Yukarıda gösterilen Html.DropDownList aşırı yüklemesi, modele bağlanacak alanın adını alır. SelectList nesnesi içeren bir ViewBag nesnesini aramak için de bu adı kullanır. Bu aşırı yüklemeyi kullanarak, ViewBag SelectList nesnesini GenreIdadlandırmanız gerekir. İkinci parametre (String.Empty), hiçbir öğe seçilmediğinde görüntülenecek metindir. Yeni bir albüm oluştururken tam olarak bunu istiyoruz. İkinci parametreyi kaldırdıysanız ve aşağıdaki kodu kullandıysanız:

@Html.DropDownList("GenreId")

Seçme listesi varsayılan olarak ilk öğeyi veya örneğimizdeki Rock öğesini kullanır.

Varsayılan ilk öğenin görüntüsü

yöntemi inceleniyor HTTP POST Create .

//

// 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);

}

Yönteminin Create bu aşırı yüklemesi, ASP.NET MVC model bağlama sistemi tarafından gönderilen form değerlerinden oluşturulan bir album nesnesi alır. Yeni bir albüm gönderdiğinizde, model durumu geçerliyse ve veritabanı hatası yoksa, yeni albüm veritabanına eklenir. Aşağıdaki görüntüde yeni bir albümün oluşturulması gösterilmektedir.

Yeni albüm oluşturmayı gösteren resim

MVC model bağlamasının albüm nesnesini oluşturmak için kullandığı ASP.NET gönderilen form değerlerini incelemek için fiddler aracını kullanabilirsiniz.

Fiddler aracının görüntüsü.

ViewBag SelectList Oluşturmayı Yeniden Düzenleme

Edit Hem yöntemler hem HTTP POST Create de yöntem, ViewBag'te SelectList'i ayarlamak için aynı koda sahiptir. DRY ruhuyla bu kodu yeniden düzenleyeceğiz. Bu yeniden düzenlenmiş kodu daha sonra kullanacağız.

ViewBag'e bir tür ve sanatçı SelectList eklemek için yeni bir yöntem oluşturun.

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);

}

ve Edit yöntemlerinin her birinde Create öğesini ayarlayıp ViewBag yöntemini çağıran SetGenreArtistViewBag iki satırı değiştirin. Tamamlanmış kod aşağıda gösterilmiştir.

//

// 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);

}

Değişikliklerin çalıştığını doğrulamak için yeni bir albüm oluşturun ve bir albümü düzenleyin.

SelectList'i DropDownList'e Açıkça Geçirme

ASP.NET MVC iskelesi tarafından oluşturulan oluşturma ve düzenleme görünümleri aşağıdaki DropDownList aşırı yüklemesini kullanır:

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"

)

Oluşturma DropDownList görünümü için işaretleme aşağıda gösterilmiştir.

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

ViewBag için SelectList özelliği adlı GenreIdolduğundan DropDownList yardımcısı ViewBag'teki SelectList değerini kullanırGenreId. Aşağıdaki DropDownList aşırı yüklemesinde açıkça SelectList geçirilir.

public static MvcHtmlString DropDownList(

    this HtmlHelper htmlHelper,

    string name,            // The name of the ViewModel property to bind.

    IEnumerable selectList  // The SelectList

)

Views\StoreManager\Edit.cshtml dosyasını açın ve yukarıdaki aşırı yüklemeyi kullanarak DropDownList çağrısını SelectList'e açıkça geçecek şekilde değiştirin. Bunu Tarz kategorisi için yapın. Tamamlanmış kod aşağıda gösterilmiştir:

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

Uygulamayı çalıştırın ve Yönetici bağlantısına tıklayın, ardından bir Jazz albümüne gidin ve Düzenle bağlantısını seçin.

Düzenlenecek Jazz albümü seçiminin görüntüsü

Şu anda seçili olan tür olarak Jazz'ı göstermek yerine Rock görüntülenir. Dize bağımsız değişkeni (bağlanacak özellik) ve SelectList nesnesi aynı ada sahip olduğunda, seçili değer kullanılmaz. Sağlanan seçili değer olmadığında, tarayıcılar varsayılan olarak SelectList'teki ilk öğeye (yukarıdaki örnekte Rock değeridir) ayarlanır. Bu, DropDownList yardımcısının bilinen bir sınırlamasıdır.

Controllers\StoreManagerController.cs dosyasını açın ve SelectList nesne adlarını ve Artistsolarak Genres değiştirin. Tamamlanmış kod aşağıda gösterilmiştir:

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);

}

Türler ve Sanatçılar adları, her kategorinin kimliğinden daha fazlasını içerdiğinden kategoriler için daha iyi adlardır. Daha önce yaptığımız yeniden düzenlemenin bedeli ödendi. ViewBag'i dört yöntemde değiştirmek yerine, değişikliklerimiz yöntemine SetGenreArtistViewBag yalıtıldı.

Yeni SelectList adlarını kullanmak için oluşturma ve düzenleme görünümlerindeki DropDownList çağrısını değiştirin. Düzenleme görünümü için yeni işaretleme aşağıda gösterilmiştir:

<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>

Oluştur görünümü, SelectList içindeki ilk öğenin görüntülenmesini önlemek için boş bir dize gerektirir.

<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>

Değişikliklerin çalıştığını doğrulamak için yeni bir albüm oluşturun ve bir albümü düzenleyin. Rock dışında bir tarza sahip bir albüm seçerek düzenleme kodunu test edin.

DropDownList Yardımcısı ile Görünüm Modeli Kullanma

ViewModels klasöründe adlı AlbumSelectListViewModelyeni bir sınıf oluşturun. sınıfındaki AlbumSelectListViewModel kodu aşağıdakilerle değiştirin:

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);

        }

    }

}

Oluşturucu AlbumSelectListViewModel bir albüm, sanatçıların ve tarzların bir listesini alır ve albümü içeren bir nesne ve tarzlar ve sanatçılar için bir SelectList nesne oluşturur.

Sonraki adımda bir görünüm oluşturduğunuzda kullanılabilir olacak şekilde AlbumSelectListViewModel projeyi oluşturun.

öğesine StoreManagerControllerbir EditVM yöntem ekleyin. Tamamlanmış kod aşağıda gösterilmiştir.

//

// 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);

}

sağ tıklayınAlbumSelectListViewModel, Çözümle'yi seçin, ardından MvcMusicStore.ViewModels; komutunu kullanarak.

Çözümle'yi seçen görüntü

Alternatif olarak, aşağıdaki using deyimini de ekleyebilirsiniz:

using MvcMusicStore.ViewModels;

Sağ tıklayın EditVM ve Görünüm Ekle'yi seçin. Aşağıda gösterilen seçenekleri kullanın.

Görünüm Ekle iletişim kutusunu gösteren resim

Ekle'yi seçin, ardından Views\StoreManager\EditVM.cshtml dosyasının içeriğini aşağıdakilerle değiştirin:

@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>

İşaretlemeyi EditVM aşağıdaki özel durumlarla özgün Edit işaretlemeye çok benzer.

  • Görünümdeki Edit model özellikleri formdadır model.property(örneğin, model.Title ). Görünümdeki EditVm model özellikleri formdadır model.Album.property(örneğin, model.Album.Title). Bunun nedeni, görünümün görünümde EditVM olduğu gibi değil için bir AlbumAlbum kapsayıcıya geçirilmesidirEdit.
  • DropDownList ikinci parametresi ViewBag'ten değil görünüm modelinden gelir.
  • Görünümdeki EditVM BeginForm yardımcısı açıkça eylem yöntemine Edit geri gönderir. Eyleme Edit geri göndererek bir HTTP POST EditVM eylem yazmamız gerekmez ve eylemi yeniden HTTP POST Edit kullanabiliriz.

Uygulamayı çalıştırın ve bir albümü düzenleyin. URL'yi kullanacak EditVMşekilde değiştirin. Bir alanı değiştirin ve kodun çalıştığını doğrulamak için Kaydet düğmesine basın.

U R L ile görüntü, V M'yi Düzenle olarak değiştir

Hangi Yaklaşımı Kullanmalısınız?

Gösterilen üç yaklaşım da kabul edilebilir. Birçok geliştirici açıkça kullanarak ViewBag'ı 'a geçirmeyi SelectList DropDownList tercih eder. Bu yaklaşım, koleksiyon için daha uygun bir ad kullanma esnekliği vermenin ek avantajına sahiptir. Tek uyarı, nesneye ViewBag SelectList model özelliğiyle aynı adı veremeyeceğinizdir.

Bazı geliştiriciler ViewModel yaklaşımını tercih eder. Diğerleri ViewModel yaklaşımının daha ayrıntılı işaretlemesini ve oluşturulan HTML'sini dezavantaj olarak kabul eder.

Bu bölümde DropDownList'i kategori verileriyle kullanma konusunda üç yaklaşım öğrendik. Sonraki bölümde yeni kategori eklemeyi göstereceğiz.