15

私のプロジェクトのいくつかのビューには同じドロップダウンリストがあります...

したがって、そのビューの ViewModel には次のものがあります。

public IEnumerable<SelectListItem> FooDdl { get; set; }

そして、コントローラーには次のものがあります:

var MyVM = new MyVM() {
    FooDdl = fooRepository.GetAll().ToSelectList(x => x.Id, x => x.Name)
}

これまでのところとても良いです...しかし、そのddlを持つすべてのビュー/コントローラーで同じコードを実行しています...

それが最善の方法ですか?

ありがとう

4

13 に答える 13

2

ドロップダウン値のゲッターを使用してオブジェクトを作成します。

public static class DropDowns
{
    public static List<SelectListItem> Items { 
       get
       {
           //Return values
       } 
    } 
}

Razor パーシャルを作成します。

@Html.DropDownListFor(m => "ChoosenItem", DropDowns.Items, "")

部分呼び出し:

@Html.RenderPartial("DropDownItems")

最後に、コントローラーでChoosenItem値を受け取ります。単に。

于 2013-10-14T12:31:07.287 に答える
2

静的クラスも使用します。

public static class SelectLists
{
        public static IList<SelectListItem> CompanyClasses(int? selected)
        {
            var session = DependencyResolver.Current.GetService<ISession>();

            var list = new List<SelectListItem>
                           {
                               new SelectListItem
                                   {
                                       Selected = !selected.HasValue,
                                       Text = String.Empty
                                   }
                           };

            list.AddRange(session.All<CompanyClass>()
                              .ToList()
                              .OrderBy(x => x.GetNameForCurrentCulture())
                              .Select(x => new SelectListItem
                                               {
                                                   Selected = x.Id == (selected.HasValue ? selected.Value : -1),
                                                   Text = x.GetNameForCurrentCulture(),
                                                   Value = x.Id.ToString()
                                               })
                              .ToList());

            return list;
        }
}

ビューには特別なものは何もありません:

@Html.DropDownListFor(x => x, SelectLists.CompanyClasses(Model))

また、ときどき EditorTemplate も作成するため、このように再利用する方が高速です

モデル :

[Required, UIHint("CompanyClassPicker")]
public int? ClassId { get; set; }

EditorTemplate :

@model int?

@if (ViewBag.ReadOnly != null && ViewBag.ReadOnly)
{
    var item = SelectLists.CompanyClasses(Model).FirstOrDefault(x => x.Selected);

    if (item != null)
    {
        <span>@item.Text</span>
    }
}
else
{
    @Html.DropDownListFor(x => x, SelectLists.CompanyClasses(Model))    
}
于 2013-10-09T21:50:33.550 に答える
1

最初の質問は、オプション リストが ViewModel に属しているかどうかです。1、2 年前にも同じことをしましたが、最近ますます「ベスト プラクティス」として見られるのは、ViewModel ではなく ViewBag/ViewData にリストを追加することです。それはオプションであり、ワンショット ドロップダウン リストに対しても同じことをする傾向がありますが、直面しているコードの再利用に関する質問には答えません。そのために、私は 2 つの異なるアプローチを考えています (さらに 2 つのアプローチは除外しています)。

共有エディター テンプレート。ドロップダウンで表されるタイプのエディター テンプレートを作成します。この場合、ViewModel または ViewBag に可能なオプションのリストがないため、テンプレートはサーバーにオプションを提供する必要があります。これは、アクション メソッド (json を返す) をコントローラー クラスに追加することで可能になります。共有の「LookupsController」(おそらく ApiController) またはリスト項目のタイプが属するコントローラーのいずれかです。

部分的なビュー。ドロップダウン値は、いくつかのタイプに属しています。そのタイプの Controller には、部分ビューを返すアクション メソッドを含めることができます。

最初のものの利点は、ナイス@Html.EditorForコールが仕事をするということです。しかし、私は ajax の依存関係が好きではありません。その理由の一部として、私は部分的なビューを好みます。

そして 3 番目の子アクションがありますが、ここでは良いパターンではないと思います。子アクションと部分ビューの違いをグーグルで検索できます。この場合、子アクションは間違った選択です。また、ヘルパー メソッドもお勧めしません。どちらもこのユースケース用に設計されていないと思います。

于 2013-10-14T19:09:24.487 に答える
0

コードを複製したくない場合は、コードをコントローラーからヘルパー クラスに配置し、RenderPartial によってビューに実装する必要がある共有ビュー (_Layout.cshtml など) 内でドロップダウンをレンダリングします。 .

コントローラーからコードをスローしたヘルパー クラスを使用する部分ビュー _MyDropdownView.cstml を次のように作成します。

@using MyNamespace.MyHelperClass
<div id="myDropdown">@Html.DropDownListFor(model => model.Prop, MyVM as SelectList, "--Select a Property--")</div>

次に、ビュー内で:

@Html.RenderPartial("_MyDropdownView")
于 2013-10-02T20:11:34.763 に答える
0

自動的に入力する必要があるすべてのプロパティとのインターフェースを用意します。

public interface ISelectFields
{
    public IEnumerable<SelectListItem> FooDdl { get; set; }
}

これらのプロパティを必要とするすべてのビュー モデルで、そのインターフェイスを実装します。

public class MyVM : ISelectFields
{
    public IEnumerable<SelectListItem> FooDdl { get; set; }
}

を持ってBaseController、オーバーライドし、渡された をOnResultExecuting見つけてViewModel、プロパティをインターフェイスに注入します。

public class BaseController : Controller
{
    protected override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        var viewResult = filterContext.Result as ViewResult;
        if (viewResult != null)
        {
            var viewModel = viewResult.Model as ISelectFields;
            if (viewModel != null)
            {
                viewModel.FooDdl = fooRepository.GetAll().ToSelectList(x => x.Id, x => x.Name)
            }
        }
        base.OnResultExecuting(filterContext);
    }
}

これで、コントローラーは非常にシンプルになり、すべてが厳密に型指定され、DRY 原則に固執し、そのプロパティの入力を忘れることができます。コントローラーが から継承し、インターフェースBaseControllerViewModels実装している限り、常にビューで使用できます。 .

public class HomeController : BaseController
{
    public ActionResult Index()
    {
        MyVM vm = new MyVM();
        return View(vm);   //you will have FooDdl available in your views
    }
}
于 2013-10-09T21:12:28.000 に答える