Bu ASP.NET MVC SelectList'in çalışmasını nasıl sağlayabilirim?


126

Görünümde görüntülemek için denetleyicimde bir seçme listesi oluşturuyorum.

Anında yaratmaya çalışıyorum, sorta şey .. bunun gibi ...

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

Derliyor, ancak çıktı kötü ...

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

Hiçbir öğenin nasıl seçilmediğine dikkat edin?

Bunu nasıl düzeltebilirim?


1
Altı cevap ... biri favorilere eklendi ... oy yok: / +1 vereceğim
womp

Yanıtlar:


128

Ben böyle yaparım

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()
    };

İkinci bakışta neyin peşinde olduğunu bildiğimden emin değilim ...


2
Teşekkür ederim, bu meseleyi çözmeme yardımcı oldu.
Cadoo

6
Seçili öğe sorununu çözmez, ancak seçilen listeler için sihirli dizelerden kaçınmanın harika bir yoludur! Şerefe
Alan Christensen

11
Seçili öğe sorununu düzeltmek için şu kodu ekleyin: şu anda seçili müşteri SelectList sList = new SelectList(selectList, "Text", "Value", selected);neredeselected
jao

68

Bir uzatma yöntemi kullanıyorum:

kullanım

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

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

ile

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;
    }
}

Güzel. Seçili bir Func, bir defaultValue seçeneği ve belirtmek için herhangi bir varsayılan olmadan ikinci bir aşırı yükleme ekledim ve bu bir tedavi olarak çalışıyor. Bu arada, IEnumerable <SelectListItem> dönüş türünü yapmak istiyorsanız, bunun gerçekten temiz görünmesini sağlamak için getiri dönüş sözdizimini kullanabilirsiniz
Chris Meek

48

items, dataValueField, dataTextField, selectedValueParametre olarak kabul eden yapıcıyı kullanma :

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

Sonra size göre:

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

3
güzel dostum :) beğendim! bunu yapmaya çalışıyordum .. ama .Select (..) kısmını alamadım .. güzel :) bunu evde deneyeceğim, sonra :)
Pure.Krome

1
Heya Çağdaş. seçilen alanın seçilmemesi dışında harika çalışıyor. Herhangi bir fikir? Bu, MVC olayındaki bir hata mı?
Pure.Krome

2
Seçili öğe, SelectList öğesini ViewData nesnesine (ViewData ["myList"] = new SelectList .. 'de olduğu gibi) eklediğinizde ve ardından <% = Html.DropDownList ("myList")%> ile işlediğinizde çalışır. Yine de bu şekilde yapmadan seçilen öğenin çalışmasını sağlayamadım. Tuhaf.
Çağdaş Tekin

@Cagdas - merhaba tekrar dostum .. Bunu hala çözemedim :( Bu bir ViewData ile ilgili nedir ??? Kendi özelliğine sahip güçlü bir şekilde yazılmış bir ViewData var .... ???
Pure.Krome

@ Pure.Krome - Bu mülkü sorudaki örneğinizden aldım. Şimdi kod örneğini düzenliyorum. Lütfen birkaç saniye içinde düzenlememe bakın.
Çağdaş Tekin

19

Thomas Stock'un cevabından yola çıkarak, şu aşırı yüklenmiş ToSelectListyöntemleri oluşturdum :

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())
            };
        }
    }
}

Denetleyicinizde şunları yapabilirsiniz:

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

Ve son olarak Görünümünüze şunu koyun:

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

İstenilen "(Select one)"çıktıyla sonuçlanacaktır - tabii ki ilk boş öğeyi istemiyorsanız yukarıdaki optionLabel'i atlayabilirsiniz:

<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>

Güncelleme: Düzeltilmiş bir kod listesi burada XML yorumlarıyla bulunabilir.


13

Sorun, SelectList'in tasarlandığı gibi çalışmasıdır. Böcek tasarımda. Seçili Özelliği SelectedItem'de ayarlayabilirsiniz, ancak listeyi GetEnumerator () ile gezerseniz (veya Mvc bunu sizin için yaparsa) bu tamamen yok sayılır. Mvc bunun yerine yeni SelectListItems oluşturur.

SelectList ctor'unu SelectListItem [], Text-Name, Value-Name ve SelectedValue ile kullanmanız gerekir. SelectListItem'in kendisini değil, seçilmesini istediğiniz SelectListItem'in DEĞERİNİ SelectedValue olarak geçirmeyi unutmayın! Misal:

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" );

(bunu test etmedim ama aynı problemi yaşadım)

2. seçenek, selected = "selected" özelliğini alır. Bu eski güzel DataSets'e benziyor ;-)


11

Bu bir seçenektir:

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" },
}

seçilen değer için yeni SelectListItem {Selected = true, Text = "15", Value = "15"}.
Cadoo

oops, evet, 'Seçili' mülkü eklemeyi unuttum, teşekkürler Cadoo =)
murki

10

Kelimenin tam anlamıyla yapmak istediğiniz tek şey buysa, diziyi dize olarak bildirmek seçili öğe sorununu çözer:

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

7

Özelliğiniz Int, String veya Double değeri gibi basit bir nesne olmasa bile SelectList ve SelectedValue'un birlikte çalışmasını sağlamak çok basittir.

Misal:

Bölge nesnemizin şöyle bir şey olduğunu varsayarsak:

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

Ve görüş modeliniz şuna benzer:

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

Aşağıdaki koda sahip olabilirsiniz:

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

Yalnızca Region nesnesinin ToString yöntemini aşağıdaki gibi bir şeye geçersiz kılarsanız:

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

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

Bunun çalışması% 100 garantilidir.

Ancak, SelectList'i tüm koşullarda% 100 çalışır hale getirmenin en iyi yolunun, öğeler koleksiyonundaki her bir öğeye karşı DropDownList veya ListBox özellik değerini test etmek için Equals yöntemini kullanmak olduğuna gerçekten inanıyorum.


5

Görünüşe göre, güçlü bir şekilde yazılmış bir görünümünüz varsa, açılır listenin kimliğini, devralınan sınıftaki bir özelliğin adı OLMAMASI için değiştirmeniz gerekir. Ardından, seçili değeri FORMCollection'dan çıkarmak ve değişikliklerinizi gerçekleştirmeden önce örneğinize koymak için düzenleme (POST) yönteminize biraz mantık eklemeniz gerekir.

Bu kesinlikle biraz tuhaf ama denedim ve işe yarıyor.

Dolayısıyla, sınıfınızda CountryId adında bir alan varsa ve ülke adlarının bir listesini görüntülüyorsanız, açılır listenin CountryId yerine CountryName kimliğine sahip olmasını sağlayın, ardından gönderide, Koleksiyon ["ÜlkeAdı"] ile bir şeyler yapabilirsiniz. .


1
Evet, aynı sorunu yaşadım. Sadece adı değiştirmek işe yaradı. Teşekkürler!
davekaro

4

Aynı sorunu yaşadım. Çözüm basit. DropDownList yardımcısına iletilen "name" parametresini, ViewModel'inizde mevcut olan özelliklerin hiçbiriyle eşleşmeyen bir şeye değiştirin. buradan daha fazlasını okuyun: http://www.dotnetguy.co.uk/post/2009/06/25/net-mvc-selectlists-selected-value-does-not-get-set-in-the-view

Dan Watson'dan alıntı yapıyorum:

MVC'de, görünüm güçlü bir şekilde yazıldıysa, seçim listesinin seçili seçeneği geçersiz kılınır ve kurucuda ayarlanan seçili seçenek özelliği hiçbir zaman görünüme ulaşmaz ve bunun yerine açılır menüdeki ilk seçenek seçilir (neden hala biraz gizemlidir) .

şerefe!


3

Tüm bu yanıtlar harika görünüyor, ancak denetleyicinin verileri iyi bilinen yapılandırılmış bir formatta bir View için hazırladığı görülüyor, buna karşılık görünümün model aracılığıyla sunulan bir IEnumerable <> 'ı yinelemesine ve standart bir seçim listesi oluşturmasına izin verdikten sonra DefaultModelBinder seçilen öğeyi bir eylem parametresi aracılığıyla size geri teslim edin. Evet, hayır, neden olmasın? Endişelerin ayrılığı, evet? Denetleyicinin UI ve View'e özgü bir şey oluşturması garip görünüyor.


3

Basit:

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

2

Ben sadece böyle koştum ve hiç problem yaşamadım

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();
        }

ve

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

bunu yaparsanız da işe yaradı,

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();
        }

ve

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

1

Örneğinizi kullanarak bu benim için çalıştı:

kontrol:

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

görünüm:

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

Evet bu benim için de çalışıyor. Benim durumumda, liste bir Varlık Modeli nesnesidir. Denetleyici: ViewData ["Kategoriler"] = new SelectList (db.Categories.ToList (), "CategoryId", "CategoryName", "15"); Görünüm: Html.DropDownList ("CategoryId", (SelectList) ViewData ["Kategoriler"], "--select--")
Junior Mayhé

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

Bunu böyle yapıyorum:

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 () sorunları halleder.


1

DropDownList'inize rastgele bir metin iletmek istiyorsanız, örneğin --Seçin-- bu kodu kullanarak bunu kolayca yapabilirsiniz:

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

0

ViewData'nızda bazı belirsizlikler olabilir:

Buraya bir göz atın


0

modelde seçilen değer, varsayılan öğe yerine avantaj sağlar. (Tüm yazıları okumadığımı kabul ediyorum)


0

Mvc 1'in nasıl kurulduğunu hatırlayamıyorum ama görünüşe göre seçim listesinin ait olduğu alanla aynı adı vermesini istiyordu ...

Birinin yukarıda söylediği gibi bulduğum şey, seçilen listelerimin, gönderildikleri ViewData'nın alanla aynı adı verildiğinde mvc2'de çalışmadığıdır.

Örneğin:

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

ne zaman çalışır

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

"ForID" ViewData adı, çalıştığı alanla aynı olduğundan çalışmaz


0

Olası bir açıklama, bağladığınız seçim listesi değerinin bir dize olmamasıdır.

Öyleyse bu örnekte, 'PageOptionsDropDown' parametresi modelinizdeki bir dize mi? Çünkü değilse, listede seçilen değer gösterilmeyecektir.


0

Html.DropDownList uzantı yönteminde MVC 2 için kaynak koduna bakarsanız, SelectList sınıfının SelectedValue özelliğini asla kontrol etmez. Sadece Modelinizle eşleşmeye çalışacaktır.

Yukarıdakilerin tümü bir temanın tüm varyasyonlarıdır, yani bir açılır liste için görünüme bir grup veriyi nasıl gönderirsiniz ve hepsi birbirleri kadar iyidir (az ya da çok).

Sorun görüşte. Ayarladığınız seçme değerine uyan kendi DropDownList uzantı yönteminizi oluşturun veya elle yineleyin. Hangisi sizin için en iyisidir.


@Franz Antesberger de aynı şeyi söylüyor.
Simon Halsey

0

Modelinizde bir koleksiyonunuz varsa ve Görünümünüz güçlü bir tipse, bunun bazı varyasyonları işe yarayacaktır:

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

-veya-

@Html.DropDownList("RegionID", 
    new SelectList(Model.Regions, "RegionID", "RegionName", Model.RegionID))
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.