2011-08-28 3 views
5

こんにちは、私はMVC3とRazorにはかなり新しく、過去数日間は私の頭の中で頑張っています。私はMVCビューでドロップダウンリストをソートするヘルパーメソッドを作成するために、プロジェクトアーキテクトの仕事を与えられました。私はコントローラからさまざまなデータを取得するビューを持っていて、ドロップダウンリストに表示したい値をいくつか戻しています。私はコントローラでそれをソートしないように、またソートするフィールドをヘルパーメソッドに渡すように言われました。私は以下のようにそれを行うことができますが、建築家は、cシャープコードの自由なビューを維持したい:ヘルパーメソッドを使用してMVC3/RazorのDropDownListを並べ替えるのに最適な方法

@Html.DropDownListFor(model => model.StudyName, new SelectList(ViewBag.StudyTypes, "Value", "Text").OrderBy(l => l.Text)) 

は、だから私は試してみて、それを動作させるためにいくつかのサンプルコードといくつかの拡張メソッドを作成しました。私の考えは、既存のHtml.DropDownListメソッドを複製し、 'オブジェクトhtmlAttributes'の受け渡しを許可し、メソッド呼び出しの一部としてスタイルを設定できるようにすることです。

ここまでは私のコードです。私は編集コントローラメソッドでViewBag.StudyTypesのドロップダウンのためのデータを返すよ:

public ActionResult Edit(int id) 
{ 
    IEnumerable<SelectListItem> mySelectList = new List<SelectListItem>(); 
    IList<SelectListItem> myList = new List<SelectListItem>(); 

    for (int i = 0; i < 5; i++) 
    { 
     myList.Add(new SelectListItem() 
      { Value = i.ToString(), Text = "My Item " + i.ToString(), Selected = i == 2 } 
     ); 
    } 

    mySelectList = myList; 
    ViewBag.StudyTypes = mySelectList; 

    StudyDefinition studydefinition = db.StudyDefinitions.Find(id); 

    return View(studydefinition); 
} 

ここに私のビューのコードがあります:最後に、以下の

@model MyStudyWeb.Models.StudyDefinition 

@using MyStudyWeb.Helpers 

@{ 
    ViewBag.Mode = "Edit"; 
} 
<div> 
    @Html.DropDownListSorted(new SelectList(ViewBag.StudyTypes, "Value", "Text"))<br /> 
    @Html.DropDownListSorted("MyList", new SelectList(ViewBag.StudyTypes, "Value", "Text"))<br /> 
</div> 

は私がしようとしている拡張メソッドです仕事を始める。最初の拡張メソッドは何もしません、私はちょうどビューのその時点で空白を取得します。 2つ目の方法は動作しますが、それは醜いです。 3番目のメソッドでは、IEnumerableのOrderByがLinq式を期待しているため、 'order by'パラメータを指定する方法はわかりません。

namespace StudyDefinition.Helpers 
{ 
    public static class HtmlHelperExtensions 
    { 
     // 1st sort method: sort the passed in list and return a new sorted list 
     public static SelectList DropDownListSorted(this HtmlHelper helper, IEnumerable<SelectListItem> selectList) 
     { 
      var x = new SelectList(selectList.ToList()).OrderBy(l => l.Text); 

      return x as SelectList; 
     } 

     // 2nd sort method: return IHtml string and create <select> list manually 
     public static IHtmlString DropDownListSorted(this HtmlHelper helper, string name, SelectList selectList) 
     { 
      StringBuilder output = new StringBuilder(); 
      (selectList).OrderBy(l => l.Text); 

      output.Append("<select id=" + name + " name=" + name + ">"); 

      foreach (var item in selectList) 
      { 
       output.Append("<option value=" + item.Value.ToString() + ">" + item.Text + "</option>"); 
      } 

      output.Append("</select>"); 

      return MvcHtmlString.Create(output.ToString()); 
     } 

     // 3rd sort method: pass in order by parameter - how do I use this? 
     public static IHtmlString DropDownListSorted(this HtmlHelper helper, string name, SelectList selectList, string orderBy) 
     { 
      StringBuilder output = new StringBuilder(); 

      //How do I use the orderBy parameter? 
      (selectList).OrderBy(l => l.Text); 

      output.Append("<select id=" + name + " name=" + name + ">"); 

      foreach (var item in selectList) 
      { 
       output.Append("<option value=" + item.Value.ToString() + ">" + item.Text + "</option>"); 
      } 

      output.Append("</select>"); 

      return MvcHtmlString.Create(output.ToString()); 
     }   
    } 
} 

私は本当に取るべき最善のアプローチを知らない、私は完全に欠落していると私は私が木のための木を見ることができないポイントであるかもしれないことをはるかに簡単な方法があるかもしれませんもういくつかの質問

  • 私はSelectListまたはMvcHtmlString、または完全に何かを返しますか?

  • 最初の拡張方法については、返されたSelectListをビューでレンダリングする方法を教えてください。

  • ソート順を指定する拡張メソッドにパラメータを渡すにはどうすればよいですか?

  • 'object htmlAttributes'パラメータを渡すにはどうすればいいですか、このオブジェクト/パラメータをSelectListにどのように適用するのですか?

、誰もがいくつかのアイデアや提案を持っている場合、私はいくつかのフィードバックをいただければと思います:)

答えて

5

最初に、あなたのコードの最も重要な部分が(どの個人的に私の任意ViewBag/ViewDataを取り除くことであろうMVCアプリケーションのガンとして考えてください)、ビューモデルと強く型付けされたビューを使用します。

それでは、私たちの見解は、(この例ではdropdownlistg)で作業されるデータを表すことになり、ビューモデルを定義することから始めてみましょう:

public class MyViewModel 
{ 
    public string SelectedItem { get; set; } 
    public IEnumerable<SelectListItem> Items { get; set; } 
} 

その後、私たちは、コントローラを持つことができます:

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     var model = new MyViewModel 
     { 
      // I am explicitly putting some items out of order 
      Items = new[] 
      { 
       new SelectListItem { Value = "5", Text = "Item 5" }, 
       new SelectListItem { Value = "1", Text = "Item 1" }, 
       new SelectListItem { Value = "3", Text = "Item 3" }, 
       new SelectListItem { Value = "4", Text = "Item 4" }, 
      } 
     }; 
     return View(model); 
    } 
} 

とビュー:

@model MyViewModel 
@Html.DropDownListForSorted(
    x => x.SelectedItem, 
    Model.Items, 
    new { @class = "foo" } 
) 

、最終的に最後のピースが満たさヘルパーです値でドロップダウンを並べ替えますHOD(テキストでソートするためにそれを適応させることができ):

public static class HtmlExtensions 
{ 
    public static IHtmlString DropDownListForSorted<TModel, TProperty>(
     this HtmlHelper<TModel> helper, 
     Expression<Func<TModel, TProperty>> expression, 
     IEnumerable<SelectListItem> items, 
     object htmlAttributes 
    ) 
    { 
     var model = helper.ViewData.Model; 
     var orderedItems = items.OrderBy(x => x.Value); 
     return helper.DropDownListFor(
      expression, 
      new SelectList(orderedItems, "Value", "Text"), 
      htmlAttributes 
     ); 
    } 
} 
+0

こんにちは@ダリン大変ありがとうございます。しかし、私は既存のシステムで作業していますが、すべてのビューには複数のドロップダウンリストがあり、ViewBagプロパティとしてコントローラからすべて返されます。だから私は本当にこのアプローチを変えることはできません。次に、ビューはすでにエンティティクラスである「リターンビュー(調査定義)」を行っています。ビューモデルを返すことができる別の方法はありますか?第3に、あなたの拡張メソッドを追加すると、DropDownListForメソッドが認識されません。 'System.Web.Mvc.HtmlHelper'に 'DropDownListFor'の定義が含まれていません。 –

+3

@Ciaran Bruen、既存のシステムとViewBag 。私はちょうどこの悪い習慣を避けるために、将来のコードのためにそれを言った。複数のドロップダウンリストがある場合は、ビューモデルに複数の 'IEnumerable 'プロパティを持つだけです。 'return view(studydefinition)'に関しては、ビューモデルをビューに渡す正しい方法です。第3に、 'DropDownListFor'拡張メソッドは' System.Web.Mvc.Html'名前空間に定義されていますので、単に 'DropDownListForSorted'ヘルパーを含むファイルの先頭にあるこの名前空間にusingを追加してスコープに入れてください。 –

0

あなたはあなただけの並べ替え要素

using (BDMMContext dataContext = new BDMMContext()) 
{ 
foreach (Arquiteto arq in dataContext.Arquitetos.SqlQuery("SELECT * FROM Arquitetos ORDER BY Nome")) 
        { 
         SelectListItem selectItem = new SelectListItem { Text = arq.Nome, Value = arq.Arquiteto_Id.ToString() }; 
         // 
         list.Add(selectItem); 
        } 
} 
0

を定義するためにクエリを使用することができますデータベースを使用している場合項目をドロップダウンリストに戻す前にソートを追加します。

この操作を行います。

モデル:StudyViewModel.cs

public class StudyViewModel { 
    public string StudyName { get; set; } 
    public string StudyTypes { get; set; } 
} 

コントローラー:StudyController.cs

using System.Web.Mvc; 
public class StudyController 
{ 
    public List<SelectListItem> studyTypes() 
    { 
     List<SelectListItem> itemList = new List<SelectListItem>(); 
     for (var i=0; i<5; i++) 
     { 
      itemList.Add = new SelectListItem({ 
       Value = i.ToString(); 
       Text = "My Item"; 
      }); 
     } 
     // You can sort here.... 
     List<SelectListItem> sortedList = itemList.OrderBy(x=>x.Text); 
     return sortedList; 
    } 

    public ActionResult Edit(int id) 
    { 
     //You won't need this because you get it using your 
     //controller's routine, instead 
     //ViewBag.StudyTypes = studySlots.OrderBy(e => e.Value); 

     //-- unless you need to add these values to the model for 
     // some reason (outside of filling the ddl), in which case.... 
     // StudyViewModel svm = new StudyViewModel(); 
     // svm.StudyTypes = studySlots.OrderBy(e => e.Value); 
     // svm.StudyName = "My Item"; 
     // return View(svm); 

     // Otherwise, just.... 
     return View(); 
    } 
} 

ビュー:Edit.cshtml

@Html.DropDownListFor(model => model.StudyName) 
    .OptionLabel('Select...') 
    .DataTextField('Text') 
    .DataValueField('Value') 
    .Datasource(source => 
    { 
     // This is where you populate your data from the controller 
     source.Read(read => 
     { 
      read.Action("studyTypes", "Study"); 
     }); 
    }) 
    .Value(Model.StudyName != null ? Model.StudyName.ToString() : "") 
) 

この方法でViewBagsを回避し、値を直接入力する機能を使用します。

関連する問題