web-dev-qa-db-ja.com

asp.net mvc3事前選択Html.DropDownListオタクディナーで動作しない場合

ドロップダウンリストについて学び、 Scott Guのブログ のようにnerddinnerのRSVP作成ページをHtml.DropDownListで追加しようとしています。利用可能なディナーを一覧表示します。

ドロップダウンリストにデータを入力することはできますが、必要な値(「サンプルディナー2」)を事前に選択するためのドロップダウンを取得できません。イニシライザーを使用して、dbにいくつかのディナーオブジェクトをシードします。データベースは、EFの「コードファーストアプローチ」を使用したSQL CE4です。申し訳ありませんが、これは一般的な問題であり、質問するのは嫌ですが、正直なところ、これにはかなりの時間を費やしていますが、機能させることができません。

ViewModel

public class RSVPViewModel
{
    public SelectList DinnersList { get; set; }
    public RSVP Rsvp { get; set; }
    public string SelectedItem { get; set; }
}

コントローラー

    //
    //GET: /RSVP/Create

    public ActionResult Create()
    {
        RSVP rsvp = new RSVP();
        string selected = "Sample Dinner 2";
        var typeList = new SelectList(dbc.Dinners.ToList(), "DinnerID", "Title", selected);

        var viewModel = new RSVPViewModel { DinnersList = typeList, Rsvp = rsvp, SelectedItem = selected };

        return View("Create", viewModel);
    }

表示

@Html.DropDownListFor(model => model.Rsvp.DinnerID, Model.DinnersList)

HTML結果

<select data-val="true" data-val-number="The field DinnerID must be a number." data-val-required="The DinnerID field is required." id="Rsvp_DinnerID" name="Rsvp.DinnerID">
     <option value="1">Sample Dinner 1</option>
     <option value="2">Sample Dinner 2</option>
</select>

したがって、ページが読み込まれるときに、値が「SampleDinner2」のドロップダウンリストを事前に選択していません。選択して[送信]をクリックすると、リストに[OK]と表示され、正しいDinnerIDが設定されます。

これも試してください:

@Html.DropDownListFor(x => x.SelectedItem, Model.DinnersList)

ただし、Rsvp.DinnerIDを設定またはバインドしません。

これはリストから事前選択しますが、バインドしません(またはRsvp.DinnerIDを設定します)

@Html.DropDownList("DinnersList")

私はそれをmvc3のままにしておきたいので、ViewModelアプローチ(ViewDataなし)を使用して、できればHtml.DropDownListFor(Html.DropDownListではなく)を使用して強い型で実装したいと思います。この場合、Viewbagは不要のようです。

ありがとう!

Edit1

SelectListItemsのselectListを使用する必要があると考えて、この冗長なアプローチを試しました。

RSVP rsvp = new RSVP();
string selected = "2";
List<SelectListItem> dinners = new List<SelectListItem>();

foreach (Dinner dinner in dbc.Dinners.ToList())
{
    SelectListItem slDinner = new SelectListItem();
    slDinner.Value = dinner.DinnerID.ToString();
    slDinner.Text = dinner.Title;
    slDinner.Selected = (slDinner.Value == selected);
    dinners.Add(slDinner);
 }

 var dinnersList = new SelectList(dinners, "Value", "Text", selected);
 var viewModel = new RSVPViewModel { DinnersList = dinnersList, Rsvp = rsvp, SelectedItem = selected };

しかし、まだ仕事はありません。 @ Html.DropDownListFor ..のViewModelSelectedItemプロパティを使用する必要がありますか?何かのようなもの :

@Html.DropDownListFor(x => x.SelectedItem, Model.DinnersList)

しかし、Rsvp.DinnerIDを設定するために選択した値を取得する方法。それはバインディングと呼ばれていると思います。

14
Jay

ここここ を読んだ後、HtmlDropDownlistForがドロップダウンで正しいアイテムを自動的に選択する方法を最終的に理解しましたモデルに基づいて-RSVPでdinnerIDを選択します(dinner.dinnerIDへの外部キー)により、Dinner.DinnerIDのリストを含むドロップダウンでその値が事前に選択されます。必要ありませんまだSelectListまたはViewModelのselectedValueについて考えます。

解決策:

    //
    //GET: /RSVP/Create

    public ActionResult Create()
    {
        //automatically preselects matching DinnerID in the Dinner dropdownlist            
        var rsvp = new RSVP {DinnerID = 2 };

        var typeList = new SelectList(dbc.Dinners.ToList(), "DinnerID", "Title");
        var viewModel = new RSVPViewModel { DinnersList = typeList, Rsvp = rsvp};

        return View("Create", viewModel);
    }
12
Jay

SelectListコンストラクター 使用しているのは、選択した値を提供することになっていますが、選択したテキストを提供しています。あなたは試してみたいかもしれません:

    int selected = 2;
3

Html.DropDownListは、バインドされたプロパティがintの場合にのみ機能します。名前付き列挙型などの他のタイプでは、デフォルトで最初の項目になります。

モデルにプロパティを追加し、intと入力します。これにより、維持しようとしている列挙型がラップされます。

public myEnumType myProperty {get; set;} // don't bind this to Html.DropDownList

public myEnumType myPropertyAsInt {
    get {return (int)this.myProperty; }
    set {this.myProperty = (myEnumType)value; }
} // bind this instead

SelectListでSelectedを使用する必要はありません-Html.DropDownListは正常に同期します。

2
David Steele

QUERY STRING with same nameがある場合は注意してください。これにより、その動作が上書きされます。同じ名前のHIDDENFIELDSについてはわかりません。

例えば。

DropDownListForは、見つかった場合、DinnerIDのクエリ文字列の値を使用します

2

Html.DropDownListはintプロパティ、DropDownListForも受け入れますが、何をしているのか注意する必要があります。 ASP.NET MVC 3のSelectExtensions.csを調べたところ、次のことがわかりました。

DropDownList( "XyField"、 "default")を使用してDropDownを作成する場合は、選択リストをViewBag.XyFieldに配置する必要があり、DropDownList()がこれを正しく処理します。

DropDownListFor(m => m.XyField、...)を使用すると、次のように、選択リストを明示的に渡すことができます。DropDownListFor(m => m .XyField、ViewBag .XyFieldList as IEnumerable)

これを行うと、次のことが起こります。

  • DropDownListFor(...)の2番目のパラメーターは、オプションのソースとして使用されます
  • 「XyField」のModelStateエントリがある場合、これがモデル値として使用されます
  • モデルの状態がなく、Html.ViewData.Eval( "XyField")がnull以外を返す場合、この値がモデル値として使用されます。
  • 見つかったモデル値がnullでない場合は、CultureInfo.CurrentCultureを使用して文字列に変換され、この値がSelectListItem値と比較されて、リストオプションが事前に選択されます。

ここでの注意:選択リストをViewBag.XyFieldに保存した場合、モデルにアクセスする前に検索されます。「selectList.ToString()」と「selectList [i」を比較したくない] .Value」をクリックして、オプションを事前に選択します。選択リストを別の場所に保存してください!

面白いことに、DropDownList()から期待するのと同じように、暗黙の選択リストでDropDownListForを使用できます。この場合、リストをViewBag.XyFieldに保存することもできます。これを機能させるには、2番目のパラメーターとしてnullを指定してヘルパーを呼び出す必要があります。DropDownListFor(m => m .XyField、null)

次に、選択リストがViewBag.XyFieldからプルされ、上記のリストのステップ3はスキップされます。したがって、XyFieldがモデル状態の場合、これは選択リスト内の独自のSelectedプロパティよりも優先されますが、それ以外の場合、選択リストは「そのまま」使用されます。

あいさつロルフ

1
Rolf