이 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
답변 6 개 ... 즐겨 찾기 1 개 ...
공감 금지

답변:


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

6
선택한 항목 문제를 해결하지는 않지만 선택 목록의 마법 문자열을 피하는 좋은 방법입니다! 건배
Alan Christensen

11
선택한 품목 문제를 해결하려면 다음 코드를 추가하십시오 . 현재 선택된 고객은 SelectList sList = new SelectList(selectList, "Text", "Value", selected);어디에 있습니까selected
jao

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 옵션 및 기본값을 지정하지 않고 두 번째 오버로드를 추가했으며 이는 문제를 해결합니다. 그런데 리턴 타입 IEnumerable <SelectListItem>을 만들고 싶다면 yield return 구문을 사용하여 이것이 정말로 깨끗해 보일 수 있습니다.
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
SelectList 항목을 ViewData 객체에 추가하면 (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는 대신 새 SelectListItem을 만듭니다.

SelectList ctor를 SelectListItem [], Text-Name, Value-Name 및 SelectedValue와 함께 사용해야합니다. SelectListItem 자체가 아니라 선택하려는 SelectListItem의 값을 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" );

(이것을 테스트하지는 않았지만 같은 문제가 있습니다)

두 번째 옵션은 selected = "selected"속성을 얻습니다. 좋은 오래된 DataSets처럼 보입니다. ;-)


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

선택한 값에 대해 new SelectListItem {Selected = true, Text = "15", Value = "15"}입니다.
Cadoo 2016 년

죄송합니다. 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

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

나는 Dan Watson을 인용한다.

MVC에서보기가 강력하게 입력되면 선택 목록의 선택된 옵션이 재정의되고 생성자에 설정된 선택된 옵션 속성이보기에 도달하지 않고 드롭 다운의 첫 번째 옵션이 대신 선택됩니다 (왜 여전히 미스터리인지 약간) .

건배!


3

이 모든 대답은 훌륭해 보이지만 컨트롤러가 잘 알려진 구조적 형식으로 View에 대한 데이터를 준비하는 것보다 뷰가 모델을 통해 전달 된 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 [ "카테고리"] = 새 SelectList (db.Categories.ToList (), "CategoryId", "CategoryName", "15"); 보기 : Html.DropDownList ( "CategoryId", (SelectList) ViewData [ "카테고리"], "--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

나는 이렇게한다 :

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

임의의 텍스트를 DropDownList에 전달 하려면 ( 예 : --Select) 이 코드를 사용하여 쉽게 수행 할 수 있습니다.

@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 속성을 확인하지 않습니다. 그것은 당신의 모델과 일치하려고 시도 할 것입니다.

위의 모든 주제는 테마에 대한 모든 변형입니다. 즉, 드롭 다운 목록을 위해 뷰에 많은 데이터를 보내는 방법은 모두 서로 비슷합니다 (더 많거나 적음).

문제가 있습니다. 설정 한 선택 값을 고려하여 직접 DropDownList 확장 메소드를 작성하거나 직접 반복하십시오. 어느 것이 당신에게 가장 잘 작동합니다.


@Franz Antesberger는 거의 같은 것을 말합니다.
Simon Halsey 2016 년

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.