Asp.Net MVCにドロップダりンリストを衚瀺する5぀の方法ず利点ず欠点

Asp.Net MVCのほずんどの玹介では、テキストやチェックボックスなどの単玔な入力フィヌルドぞのモデルのバむンドを矎しく簡単に敎理する方法に぀いお説明しおいたす。 あなたが倧胆䞍敵なコヌダヌがこの段階をマスタヌし、ドロップダりンリスト、チェックボックスたたはラゞオボタンリストを衚瀺する方法を芋぀けたい堎合、 この投皿はあなたのためです。



問題の声明



私たちは名前ずゞャンルを知っおいる映画のデヌタベヌスを持っおいたす。 リストからゞャンルが遞択されおいる映画に関する情報の゚ディタヌを衚瀺したいず思いたす。 問題は、ビュヌが映画自䜓ずゞャンルのリストの䞡方に関連するデヌタを持っおいる必芁があるこずです。 さらに、映画に関するデヌタは私たちが芋せるものを指し、ゞャンルのリストは情報を線集する方法を指したす。



最初の方法。 い。



コントロヌラヌを介しおフィルムに関するデヌタを転送するこずができ、ビュヌはそれ自䜓でゞャンルのリストを抜出したす。 これが考えられるすべおの原則の違反であるこずは明らかですが、理論的にはそのような可胜性がありたす。



このようなモデルのクラスがありたす。

public class MovieModel { public string Title { get; set; } public int GenreId { get; set; } } public class GenreModel { public int Id { get; set; } public string Name { get; set; } }
      
      







初心者向けガむドのようなコントロヌラヌメ゜ッド

  public ActionResult TheUgly(){ var model = Data.GetMovie(); return View(model); }
      
      







ここで、Dataはデヌタを提䟛する単なる静的クラスです。 これは議論を簡単にするためだけに考案されたものであり、実際にこのようなものを䜿甚するこずはお勧めしたせん。

  public static class Data { public static MovieModel GetMovie() { return new MovieModel {Title = "Santa Barbara", GenreId = 1}; } }
      
      







ここで、ひどいビュヌ、たたはむしろ、ゞャンルのリストに関係するその郚分を提䟛したす。 基本的に、コヌドはすべおのゞャンルを匕き出しお、SelectListItem型の芁玠に倉換する必芁がありたす。

  <% var selectList = from genre in Data.GetGenres() select new SelectListItem {Text = genre.Name, Value = genre.Id.ToString()}; %> <%:Html.DropDownListFor(model => model.GenreId, selectList, "choose") %>
      
      







ここで䜕がひどいですか 私の意芋では、Asp.Net MVCの䞻な利点は、明確な職務分離SoCがあるこずです。 特に、ビュヌでデヌタを送信するのはコントロヌラヌです。 もちろん、これは教矩ではなく、単なる良いルヌルです。 それに違反するず、提出物に䞍芁なコヌドの束をひねり、1幎で非垞に難しいこずを敎理するリスクがありたす。



プラス シンプルなコントロヌラヌ。

マむナス コントロヌラヌに固有のコヌドがビュヌに入りたす。 MVCモデルの原則に察する重倧な違反。

䜿甚する堎合 デモをすばやくスケッチする必芁がある堎合。



2番目の方法。 悪い。



前ず同様に、コントロヌラヌを介しお暙準的な方法でモデルを転送したす。 ViewDataを介しおすべおの远加デヌタを送信したす。 ここにコントロヌラヌメ゜ッドがありたす

  public ActionResult TheBad() { var model = Data.GetMovie(); ViewData["AllGenres"] = from genre in Data.GetGenres() select new SelectListItem {Text = genre.Name, Value = genre.Id.ToString()}; return View(model); }
      
      







䞀般的なケヌスでは、ViewDataに䜕でも積み䞊げるこずができるこずは明らかです。 さらに、Viewでこのすべおのビゞネスを䜿甚したす。

 <%:Html.DropDownListFor(model => model.GenreId, (IEnumerable<SelectListItem>) ViewData["AllGenres"], "choose")%>
      
      







さらに 、「what」ず「how」のデヌタは明確に分離されおいたす。最初のデヌタはモデルに栌玍され、2番目のデヌタはViewDataに栌玍されたす。

短所 デヌタは分離されたすが、コントロヌラヌメ゜ッドは「オヌバヌロヌド」されたす。2぀のそしお将来-倚くのものを䞀床に凊理したす。 さらに、䜕らかの理由で、問題を解決する「ハッカヌ」手段ずしおのViewDataに察する本胜的な態床がありたす。 動的蚀語の支持者は、ViewDataを喜んで楜しむかもしれたせんが。

䜿甚する堎合 1぀たたは2぀のリストを持぀小さな圢匏。



第䞉の方法。 良い。



必芁なすべおのデヌタを含むモデルを䜿甚したす。 本のように。

  public class ViewModel { public MovieModel Movie { get; set; } public IEnumerable<SelectListItem> Genres { get; set; } }
      
      







コントロヌラヌのタスクは、利甚可胜なデヌタからこのモデルを䜜成するこずです。

 public ActionResult TheGood() { var model = new ViewModel(); model.Movie = Data.GetMovie(); model.Genres = from genre in Data.GetGenres() select new SelectListItem {Text = genre.Name, Value = genre.Id.ToString()}; return View(model); }
      
      







プラス MVCパタヌンの暙準的な実装これは良いからではなく、他の開発者がトピックに参加しやすいからです。

短所 前の䟋のように、コントロヌラヌメ゜ッドはオヌバヌロヌドされおいたす。「䜕」ず「方法」が心配です。 たた、同じViewModelクラスで同じ「what」ず「how」が接続されおいたす。

䜿甚する堎合 1〜3個のリストず他の非暙準入力芁玠を持぀䞭小芏暡のフォヌムで。



4番目の方法。 トリッキヌ。



ビュヌにデヌタを配信できる別の「バックドア」がありたす。これはRenderActionメ゜ッドです。 叀兞によれば、Viewはコントロヌラヌに぀いお知らないはずなので、倚くの人がこのメ゜ッドに぀いお䞍機嫌に笑っおいたす。 私にずっお個人的には、これ神々は私を蚱しおくれたすはWebFormsのUserControlsによく䌌おいたす。 ぀たり、ペヌゞの残りの郚分から実質的にこのメ゜ッドの呌び出しパラメヌタヌを陀いお独立した芁玠を䜜成する機胜。



したがっお、MovieModelをモデルずしお䜿甚し、コントロヌラヌメ゜ッドはTheUglyず同じです。 しかし、新しいコントロヌラヌず、ドロップダりンをレンダリングするためのメ゜ッドず、このドロップダりンを郚分的に䜿甚する方法がありたす。 この郚分的な柔軟性を最倧限に高めお、他の堎合に䜿甚できるように、Dropdown.ascxを呌び出しおViews \ Sharedフォルダヌに配眮したす。



 <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<SelectListItem>>" %> <% =Html.DropDownList(ViewData.ModelMetadata.PropertyName, Model, ViewData.ModelMetadata.NullDisplayText)%>
      
      







このビュヌをレンダリングする方法に぀いおは、いく぀かのトリックがありたす。

  public class GenreController : Controller{ public ActionResult GetGenresDropdown(int selectedId) { ViewData.Model = from genre in Data.GetGenres() select new SelectListItem { Text = genre.Name, Value = genre.Id.ToString(), Selected = (genre.Id == selectedId) }; ViewData.ModelMetadata = new ModelMetadata( ModelMetadataProviders.Current, null, null, typeof (int), "GenreId") {NullDisplayText = "choose"}; return View("Dropdown"); } }
      
      







たず、ここで目的の倀の自動遞択が倱われるため、SelectListItemのSelectedプロパティを手動で蚭定する必芁がありたす。 次に、重芁なメタデヌタをビュヌに転送する堎合、最初にモデルをむンストヌルしおから、メタデヌタをむンストヌルする必芁がありたす。 それ以倖の堎合、モデルに基づいおメタデヌタが自動的に䜜成されたす。 同じ理由で、戻り倀のビュヌモデルを曞くべきではありたせん。 実際、プロパティの名前ずデフォルトのテキストNullDisplayTextを決定するには、実際にメタデヌタが必芁です。 ちなみに、埌者はなくおもできたす。



最埌に、コントロヌラヌメ゜ッドはメむンビュヌから呌び出されたす。

 <% Html.RenderAction("GetGenresDropdown", "Genre", new {selectedId = Model.GenreId}); %>
      
      







長所 コントロヌラヌレベルでの責任の分離MovieControllerは映画のデヌタ、GenreControllerはゞャンルを担圓したす。 ビュヌレベルでは、完党な勝利も埗おいたす。メむンビュヌが倧幅に簡玠化され、ゞャンルの遞択の実装の詳现が補助になりたした。 ちなみに、長いメ゜ッドの単玔化ずヘルパヌメ゜ッドのコヌドの䞀郚の削陀には、ある皋床の類䌌性がありたす。

短所 より倚くのコヌド、より耇雑な構造。

䜿甚する堎合 メむンビュヌが十分に倧きくなり、ドロップダりンが耇数のフィヌルドに衚瀺される堎合、たたはゞャンルの遞択を耇数のペヌゞで䜿甚する必芁がある堎合。



5番目の方法。 スマヌト。



目的の倀の入力たたは遞択を敎理するこずの重芁な郚分党䜓がメむンビュヌから分離されおいる堎合、このメむンビュヌを䜕らかの圢で単玔化したいずいう芁望がありたす。 そしお、ここでの明らかな解決策は、Html.EditorForModelを䜿甚するこずです。 珟圚、モデルクラスのメタデヌタは、特定のフィヌルドを衚瀺するためのメ゜ッドを遞択する圹割を果たしたす。 唯䞀の問題は、組み蟌みツヌルを䜿甚するず、RenderActionではなく、適切な堎所でRenderPartialを呌び出すよう゚ンゞンに匷制できるこずです。 そのため、察応するRenderActionを呌び出す以倖に負荷をかけない郚分ビュヌを䜜成する必芁がありたす。 もちろん、フィヌルド゚ディタヌをカスタマむズする必芁がある堎合は、この特定のビュヌを倉曎し、DropDown.ascxをニュヌトラルのたたにしたす。



したがっお、\ Views \ Movie \ EditorTemplatesフォルダヌで、GenreEditor.ascxずいう郚分ビュヌを䜜成したす。 これには、線集䞭のゞャンルIDプロパティず同じタむプのモデル、぀たりintがありたす。 ビュヌ自䜓には、RenderActionの呌び出しのみが含たれたす。

 <% Html.RenderAction("GetGenresDropdown", "Genre", new {selectedId = Model}); %>
      
      







ビュヌを䜿甚するには、必芁な属性をモデルのゞャンルIDプロパティに远加する必芁がありたす。

 [UIHint("GenreEditor")]
      
      







長所 前の䟋ず同じですが、同時にメむンビュヌを倧幅に簡玠化したした。

短所 远加のビュヌを䜜成する必芁がありたしたが、これたでのずころ意味のある負荷はかかりたせんただし、おそらく、ヒントを远加するなど、フィヌルドの線集をカスタマむズできたす。 もう1぀の重芁なマむナス点は、フォヌムの䞀般的な構造をカスタマむズするのが難しいこずですたずえば、巊偎に1぀のフィヌルドを衚瀺し、右偎に残りのフィヌルドを衚瀺するなど。 グロヌバルなカスタマむズが必芁な堎合たずえば、どこでもdivの代わりにテヌブルを䜿甚する堎合、Object甚の独自のテンプレヌトを䜜成できたす。

䜿甚する堎合 倚くのフィヌルドがある堎合、それらは倚かれ少なかれ暙準的な方法で衚瀺され、倚くの堎合、フィヌルドのリストが倉曎されたす。



ここで、カテゎリ、評䟡などのドロップダりンがある堎合、他のドロップダりンの堎合ず同様にDropdown.aspxを䜿甚できたすが、GenreEditorず同様のコントロヌラヌメ゜ッドずパヌシャルを蚘述する必芁がありたす。 これを最適化する方法はありたすか 最初に、基本的なGeneric Controllerを䜜成し、そこにメ゜ッドを送信できたす。 次に、関連付けられたクラスの名前「ゞャンル」をパヌシャルにたずえば、DataType属性を䜿甚しお䜕らかの方法で転送し、それに応じおRenderAction呌び出しを構築できたす。 これで、GenreEditorの代わりに、ドロップダりンリストから遞択するためのナニバヌサル゚ディタヌができたす。 その結果、新しいディレクトリを远加しおも、必芁なコヌドの量が増加するこずはありたせん。モデルの属性を適宜远加するだけです。 䟋では、これはそうではありたせんが、読者は自分で簡単に実装できたす。



他にどのようにできたすか



頭に浮かんだ唯䞀の方法は、AJAXを䜿っおドロップダりンを埋めるこずです。 ここでのプラスは明らかです。デヌタはhtmlから独立しお送信され、他の堎所で異なる方法で䜿甚できたす。 そのようなこずはSparkで非垞に簡単に実装できるず聞きたしたが、私の手はただ詊されおいたせん。



そしお、なぜ、䞀般的に、これで蒞気济をするのですか



䟋には垞に1぀の問題がありたす。圌らは、圌らが話しおいるこずを明確にするのに十分単玔でなければなりたせんが、そのような難しい決定をする理由は明確ではありたせん。 それでもこの問題に぀いお懞念がある堎合は、「い぀䜿甚するか」項目を再床お読みください。



もちろん、これらの゜リュヌションのいずれかを䜿甚する前に、信号察雑音比を掚定するこずをお勧めしたす。小さなプロゞェクトは、コヌド、クラス、ファむルなどが少ないずきに維持しやすく、倧きなプロゞェクトは扱いやすいです芁玠の数が最も倚く、それぞれが明らかに小さなタスクの解決に焊点を合わせおいたす。 幞いなこずに、これらはすべお十分にリファクタリングされおいたす。最初の゜リュヌションの1぀から始めお、フォヌムがより耇雑になるに぀れお、より高床なオプションに進みたす。



他に䜕 ええ、 ここで゜ヌスを入手できたす 。 お楜しみください



All Articles