このASP.NET MVC SelectListを機能させるにはどうすればよいですか?


126

コントローラにselectListを作成して、ビューに表示します。

私はその場でそれを作成しようとしています、このようなものです...

myViewData.PageOptionsDropDown = 
   new SelectList(new [] {"10", "15", "25", "50", "100", "1000"}, "15");

それはコンパイルされますが、出力は悪いです...

<select id="PageOptionsDropDown" name="PageOptionsDropDown">
    <option>10</option>
    <option>15</option>
    <option>25</option>
    <option>50</option>
    <option>100</option>
    <option>1000</option>
</select>

アイテムが選択されていないことに注意してください。

どうすれば修正できますか?


1
六の答え... 1お気に入りに登録しました...いいえupvotes:私はそれを1あげる/
womp

回答:


128

これが私のやり方です

IList<Customer> customers = repository.GetAll<Customer>();
IEnumerable<SelectListItem> selectList = 
    from c in customers
    select new SelectListItem
    {
        Selected = (c.CustomerID == invoice.CustomerID),
        Text = c.Name,
        Value = c.CustomerID.ToString()
    };

一見したところ、あなたが何を求めているのかわかりません...


2
これが私がこのことを理解するのを助けてくれてありがとう
Cadoo 09年

6
選択したアイテムの問題は修正されませんが、選択リストのマジックストリングを回避する優れた方法です。乾杯
アラン・クリステンセン

11
選択したアイテムの問題を修正するには、次のコードを追加します。現在選択されている顧客はSelectList sList = new SelectList(selectList, "Text", "Value", selected);どこselected
ですか

68

私は拡張メソッドを使用します:

使用法

var departmentItems = departments.ToSelectList(d => d.Code + 
                                               " - " + d.Description,
                                               d => d.Id.ToString(),
                                               " - ");

var functionItems = customerFunctions.ToSelectList(f => f.Description, 
                                                   f => f.Id.ToString(), 
                                                   " - ");

public static class MCVExtentions
{
    public static List<SelectListItem> ToSelectList<T>(
        this IEnumerable<T> enumerable, 
        Func<T, string> text, 
        Func<T, string> value, 
        string defaultOption)
    {
        var items = enumerable.Select(f => new SelectListItem()
                                     {
                                         Text = text(f), 
                                         Value = value(f) 
                                     }).ToList();
        items.Insert(0, new SelectListItem()
                    {
                        Text = defaultOption, 
                        Value = "-1" 
                    });
        return items;
    }
}

いいね。選択したFunc、defaultValueオプション、および指定するデフォルトなしの2番目のオーバーロードを追加しました。これで問題なく動作します。ちなみに、戻り値の型をIEnumerable <SelectListItem>にしたい場合は、yield戻り構文を使用して、これを本当にきれいに見せることができます
Chris Meek

48

items, dataValueField, dataTextField, selectedValueパラメーターとして受け入れるコンストラクターの使用:

ViewData["myList"] = 
                new SelectList(new[] { "10", "15", "25", "50", "100", "1000" }
                .Select(x => new {value = x, text = x}), 
                "value", "text", "15");

次にあなたの見解では:

<%=Html.DropDownList("myList") %>

3
素敵な男:)私は好きです!私はこれをしようとしていましたが、.Select(..)部分を取得できませんでした.. nice :)私は後で自宅で試してみます:)
Pure.Krome

1
Heya Cagdas。選択したフィールドが選択されていないことを除いて、うまく機能します。何か案が?これはMVC関連のバグですか?
Pure.Krome 2009

2
選択したアイテムは、ViewDataオブジェクトにSelectListアイテムを追加すると(ViewData ["myList"] = new SelectList ..のように)機能し、<%= Html.DropDownList( "myList")%>でレンダリングします。この方法を使わないと、選択したアイテムを機能させることができませんでした。変だ。
ÇağdaşTekinの

@Cagdas-こんにちはまた..私はまだこれを理解していません:( ViewDataについてこれは何ですか???私はそれ自身のプロパティで強く型付けされたViewDataを持っています... ???
Pure.Krome

@ Pure.Krome-私は問題のあなたの例からその特性を取りました。今、私はコードサンプルを編集しています。数秒後に編集内容をご覧ください。
ÇağdaşTekinの

19

Thomas Stockの答えを基に、これらのオーバーロードToSelectListメソッドを作成しました。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;

public static partial class Helpers
{
    public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, bool selectAll = false)
    {
        return enumerable.ToSelectList(value, value, selectAll);
    }

    public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, object selectedValue)
    {
        return enumerable.ToSelectList(value, value, new List<object>() { selectedValue });
    }

    public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, IEnumerable<object> selectedValues)
    {
        return enumerable.ToSelectList(value, value, selectedValues);
    }

    public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, Func<T, object> text, bool selectAll = false)
    {
        foreach (var f in enumerable.Where(x => x != null))
        {
            yield return new SelectListItem()
            {
                Value = value(f).ToString(),
                Text = text(f).ToString(),
                Selected = selectAll
            };
        }
    }

    public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, Func<T, object> text, object selectedValue)
    {
        return enumerable.ToSelectList(value, text, new List<object>() { selectedValue });
    }

    public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, Func<T, object> text, IEnumerable<object> selectedValues)
    {
        var sel = selectedValues != null
            ? selectedValues.Where(x => x != null).ToList().ConvertAll<string>(x => x.ToString())
            : new List<string>();

        foreach (var f in enumerable.Where(x => x != null))
        {
            yield return new SelectListItem()
            {
                Value = value(f).ToString(),
                Text = text(f).ToString(),
                Selected = sel.Contains(value(f).ToString())
            };
        }
    }
}

コントローラーでは、次のことを行うことができます。

var pageOptions = new[] { "10", "15", "25", "50", "100", "1000" };
ViewBag.PageOptions = pageOptions.ToSelectList(o => o, "15" /*selectedValue*/);

最後に、ビューに次のように入力します。

@Html.DropDownList("PageOptionsDropDown", ViewBag.PageOptions as IEnumerable<SelectListItem>, "(Select one)")

これにより、目的の出力が得られます。もちろん、"(Select one)"最初の空の項目が不要な場合は、上記のoptionLabelを省略できます。

<select id="PageOptionsDropDown" name="PageOptionsDropDown">
<option value="">(Select one)</option>
<option value="10">10</option>
<option selected="selected" value="15">15</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
<option value="1000">1000</option>
</select>

更新:改訂されたコードリストは、XMLコメントとともにここにあります。


13

問題は、SelectListが設計どおりに機能することです。バグはデザインにあります。SelectedItemでSelectedプロパティを設定できますが、GetEnumerator()を使用してリストをトラバースする場合(またはMvcがそれを行う場合)、これは完全に無視されます。Mvcは代わりに新しいSelectListItemsを作成します。

SelectListItem []、Text-Name、Value-Name、およびSelectedValueとともにSelectList ctorを使用する必要があります。SelectListItem自体ではなく、選択したいSelectListItemのVALUEをSelectedValueとして渡すことに注意してください!例:

SelectList sl = new SelectList( new[]{
  new SelectListItem{ Text="one", Value="1"},
  new SelectListItem{ Text="two", Value="2"},
  new SelectListItem{ Text="three", Value="3"}
}, "Text", "Value", "2" );

(これはテストしていませんが、同じ問題がありました)

次に、2番目のオプションはselected = "selected"属性を取得します。それは古き良きデータセットのように見えます;-)


11

これはオプションです:

myViewData.PageOptionsDropDown = new[] 
{
 new SelectListItem { Text = "10", Value = "10" },
 new SelectListItem { Text = "15", Value = "15", Selected = true }
 new SelectListItem { Text = "25", Value = "25" },
 new SelectListItem { Text = "50", Value = "50" },
 new SelectListItem { Text = "100", Value = "100" },
 new SelectListItem { Text = "1000", Value = "1000" },
}

選択した値の新しいSelectListItem {Selected = true、Text = "15"、Value = "15"}。
Cadoo 2009年

おっと、ええ、「選択された」プロパティを含めるのを忘れていました。Cadoo=)に感謝します
murki

10

それが文字通りあなたがしたいすべてであるならば、文字列として配列を宣言するだけで選択されたアイテムの問題を修正します:

myViewData.PageOptionsDropDown = 
   new SelectList(new string[] {"10", "15", "25", "50", "100", "1000"}, "15");

7

プロパティがInt、String、またはDouble値のような単純なオブジェクトでなくても、SelectListとSelectedValueを一緒に機能させるのは非常に簡単です。

例:

Regionオブジェクトが次のようなものであると想定します。

public class Region {
     public Guid ID { get; set; }
     public Guid Name { get; set; }
}

そしてあなたのビューモデルは次のようなものです:

public class ContactViewModel {
     public DateTime Date { get; set; }
     public Region Region { get; set; }
     public List<Region> Regions { get; set; }
}

あなたは以下のコードを持つことができます:

@Html.DropDownListFor(x => x.Region, new SelectList(Model.Regions, "ID", "Name")) 

RegionオブジェクトのToStringメソッドを次のようにオーバーライドする場合のみ。

public class Region {
     public Guid ID { get; set; }
     public Guid Name { get; set; }

     public override string ToString()
     {
         return ID.ToString();
     }
}

これは、100%の動作が保証されています。

しかし、私はすべての状況でSelectListを100%動作させる最良の方法は、Equalsメソッドを使用して、DropDownListまたはListBoxプロパティ値を項目コレクションの各項目に対してテストすることであると確信しています。


5

強く型付けされたビューがある場合、ドロップダウンのIDを変更して、継承されたクラスのプロパティの名前ではないようにする必要があるようです。次に、いくつかのロジックを編集(POST)メソッドに配置して、選択した値をFORMCollectionからプルオフし、変更をコミットする前にインスタンスに配置する必要があります。

これは確かに少し奇妙ですが、試してみましたが、うまくいきました。

したがって、クラスにCountryId sayというフィールドがあり、国名のリストを表示している場合は、ドロップダウンにCountryIdではなくCountryNameのIDを指定し、投稿でCollection ["CountryName"]を使用して何かを行うことができます。


1
はい、同じ問題がありました。名前を変更するだけでうまくいきました。ありがとう!
davekaro 2010

4

私はまったく同じ問題を抱えていました。解決策は簡単です。DropDownListヘルパーに渡された "name"パラメータを、ViewModelに存在するどのプロパティとも一致しないものに変更するだけです。詳細はこちら:http : //www.dotnetguy.co.uk/post/2009/06/25/net-mvc-selectlists-selected-value-does-not-get-set-in-the-view

私はダン・ワトソンを引用します:

MVCでは、ビューが厳密に型指定されている場合、選択リストの選択されたオプションがオーバーライドされ、コンストラクターで選択されたオプションプロパティがビューに到達せず、代わりにドロップダウンの最初のオプションが選択されます(なぜかは謎のままです)。 。

乾杯!


3

これらのすべての答えは素晴らしいようですが、コントローラーは、よく知られている構造化形式でビューのデータを準備しているのではなく、モデルを介して配信されたIEnumerable <>をビューに単純に反復させ、標準の選択リストを作成してから、DefaultModelBinderを作成しているようです選択したアイテムをアクションパラメータを介してあなたに返します。はい、いいえ、なぜですか?懸念の分離、そうですか?UIとビューに固有の何かを構築するコントローラーがあるのは奇妙に思えます。


3

シンプル:

string[] someName = new string[] {"10", "15", "25", "50", "100", "1000"};
myViewData.PageOptionsDropDown = new SelectList(someName, "15");

2

このように実行しただけで問題はありませんでした。

public class myViewDataObj
    {
        public SelectList PageOptionsDropDown { get; set; }
    }

public ActionResult About()
        {
            myViewDataObj myViewData = new myViewDataObj();
            myViewData.PageOptionsDropDown =
                  new SelectList(new[] { "10", "15", "25", "50", "100", "1000" }, "15");

            ViewData["myList"] = myViewData.PageOptionsDropDown;
            return View();
        }

そして

<%=Html.DropDownList("myList") %>

これを行ってもうまくいきました

public ActionResult About()
        {
            myViewDataObj myViewData = new myViewDataObj();
            myViewData.PageOptionsDropDown =
                  new SelectList(new[] { "10", "15", "25", "50", "100", "1000" });

            ViewData["myListValues"] = myViewData.PageOptionsDropDown;
            ViewData["myList"] = "15";
            return View();
        }

そして

<%=Html.DropDownList("myList",(IEnumerable<SelectListItem>)ViewData["myListValues"]) %>

1

あなたの例を使用すると、これは私にとってうまくいきました:

コントローラ:

ViewData["PageOptionsDropDown"] = new SelectList(new[] { "10", "15", "25", "50", "100", "1000" }, "15");

見る:

<%= Html.DropDownList("PageOptionsDropDown")%>

はい、それは私にとってもうまくいきます。私の場合、リストはエンティティモデルオブジェクトです。コントローラー:ViewData ["Categories"] = new SelectList(db.Categories.ToList()、 "CategoryId"、 "CategoryName"、 "15"); 表示:Html.DropDownList( "CategoryId"、(SelectList)ViewData ["Categories"]、 "
--select

1
MonthRepository monthRepository = new MonthRepository();
IQueryable<MonthEntity> entities = monthRepository.GetAllMonth();
List<MonthEntity> monthEntities = new List<MonthEntity>();

foreach(var r in entities)
{
    monthEntities.Add(r);
}

ViewData["Month"] = new SelectList(monthEntities, "MonthID", "Month", "Mars");

1

私はそれをこのようにします:

List<SelectListItem> list = new List<SelectListItem>{
new SelectListItem {Selected = true, Text = "Select", Value = "0"},
new SelectListItem {Selected = true, Text = "1", Value = "1"},
new SelectListItem {Selected = true, Text = "2", Value = "2"}
};
return list.ToArray();

ToArray()が問題を処理します。


1

--Select--などのランダムなテキストをDropDownListに渡したい場合は、次のコードを使用して簡単に行うことができます。

@Html.DropDownListFor(x => x.CategoryId, new SelectList(Model.Categories, "Id", "Name"), "--Select--", new { @class = "form-control" })


0

モデルで選択された値は、デフォルトのアイテムの代わりに利用されます。(私はすべての投稿を読んでいないことに同意します)


0

mvc 1の設定方法を思い出せませんが、所属するフィールドと同じ名前の選択リストが必要だったようです...

上で誰かが言ったように、私が見つけたのは、送信されたViewDataがフィールドと同じ名前であるときに、私の選択リストがmvc2で機能していなかったことです。

例えば:

<%= Html.DropDownListFor((model => model.ForID), (SelectList)ViewData["ForName"]) %>

いつ動作するか

<%= Html.DropDownListFor((model => model.ForID), (SelectList)ViewData["ForID"]) %>

ViewDataの名前 "ForID"が機能しているフィールドと同じ名前であるため、機能しません


0

考えられる説明は、バインドしている選択リストの値が文字列ではないということです。

その例では、パラメーター 'PageOptionsDropDown'はモデルの文字列ですか?そうでない場合、リストで選択された値は表示されません。


0

Html.DropDownList拡張メソッドでMVC 2のソースコードを調べても、SelectListクラスのSelectedValueプロパティはチェックされません。それはあなたのモデルに対してのみマッチしようとします。

上記はすべてテーマのバリエーションです。つまり、ドロップダウンリスト用にビューに大量のデータを送信するにはどうすればよいのでしょうか。

問題は視野にある。設定したselectvalueを尊重する独自のDropDownList拡張メソッドを作成するか、手動で繰り返します。どちらがあなたに最適か。


@フランツ・アンテスベルガーは同じことを言っています。
Simon Halsey、

0

モデルにコレクションがあり、ビューが強く型付けされている場合、これのいくつかのバリエーションが機能します。

@Html.DropDownListFor(x => x.RegionID, 
    new SelectList(Model.Regions,"RegionID", "RegionName", Model.RegionID))

-または-

@Html.DropDownList("RegionID", 
    new SelectList(Model.Regions, "RegionID", "RegionName", Model.RegionID))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.