나는 이것이 RC1이라고 시도한 다음 문제를 해결하지 못한 RC2로 업그레이드했습니다.
// in my controller
ViewData["UserId"] = new SelectList(
users,
"UserId",
"DisplayName",
selectedUserId.Value); // this has a value
결과 : SelectedValue 속성이 개체에 설정됩니다.
// in my view
<%=Html.DropDownList("UserId", (SelectList)ViewData["UserId"])%>
결과 : 예상되는 모든 옵션이 클라이언트에 렌더링되지만 선택한 속성이 설정되지 않았습니다. SelectedValue의 항목은 목록 내에 있지만 목록의 첫 번째 항목은 항상 기본적으로 선택됩니다.
어떻게해야합니까?
업데이트
John Feminella의 답변 덕분에 문제가 무엇인지 알아 냈습니다. “UserId”는 내 뷰가 강력하게 입력되는 모델의 속성입니다. Html.DropDownList ( “UserId”가 “UserId”가 아닌 다른 이름으로 변경되면 선택한 값이 올바르게 렌더링됩니다.
이로 인해 값이 모델에 바인딩되지 않습니다.
답변
이 문제를 해결 한 방법입니다.
나는 다음을 가졌다 :
제어 장치:
ViewData["DealerTypes"] = Helper.SetSelectedValue(listOfValues, selectedValue) ;
전망
<%=Html.DropDownList("DealerTypes", ViewData["DealerTypes"] as SelectList)%>
다음에 의해 변경 :
전망
<%=Html.DropDownList("DealerTypesDD", ViewData["DealerTypes"] as SelectList)%>
DropDown은 ViewData 이름이 같은 이름을 가져서는 안되는 것 같습니다 : S 이상하지만 작동했습니다.
답변
이 시도:
public class Person {
public int Id { get; set; }
public string Name { get; set; }
}
그리고:
var list = new[] {
new Person { Id = 1, Name = "Name1" },
new Person { Id = 2, Name = "Name2" },
new Person { Id = 3, Name = "Name3" }
};
var selectList = new SelectList(list, "Id", "Name", 2);
ViewData["People"] = selectList;
Html.DropDownList("PeopleClass", (SelectList)ViewData["People"])
MVC RC2를 사용하면 다음을 얻을 수 있습니다.
<select id="PeopleClass" name="PeopleClass">
<option value="1">Name1</option>
<option selected="selected" value="2">Name2</option>
<option value="3">Name3</option>
</select>
답변
DropDown의 이름을 “UserId”로 지정하고 모델 바인딩이 올바르게 작동하도록 할 수 있습니다.
이 작업을 수행하기위한 유일한 요구 사항은 SelectList를 포함하는 ViewData 키가 바인딩하려는 Model 속성과 이름이 같지 않다는 것입니다. 특정 경우에는 다음과 같습니다.
// in my controller
ViewData["Users"] = new SelectList(
users,
"UserId",
"DisplayName",
selectedUserId.Value); // this has a value
// in my view
<%=Html.DropDownList("UserId", (SelectList)ViewData["Users"])%>
그러면 모델의 UserId 속성과 이름이 같은 UserId라는 선택 요소가 생성되므로 모델 바인더는 Html.DropDownList 도우미가 생성 한 html의 선택 요소에서 선택한 값으로이를 설정합니다.
속성 이름과 동일한 키를 사용하여 ViewData에 선택 목록을 넣을 때 특정 Html.DropDownList 생성자가 SelectList에 지정된 값을 선택하지 않는 이유를 잘 모르겠습니다. 다른 시나리오에서 DropDownList 도우미가 사용되는 방식과 관련이 있다고 생각합니다. 관례는 모델의 속성과 동일한 이름을 가진 ViewData에 SelectList가 있다는 것입니다. 이것은 올바르게 작동합니다.
// in my controller
ViewData["UserId"] = new SelectList(
users,
"UserId",
"DisplayName",
selectedUserId.Value); // this has a value
// in my view
<%=Html.DropDownList("UserId")%>
답변
이것이 팀이 수정해야하는 버그라고 생각하지 않는다면 MSDN은 문서를 개선해야합니다. 혼란스러운 것은 이것에 대한 잘못된 문서에서 비롯됩니다. MSDN 에서는 매개 변수 이름을 다음 과 같이 설명합니다 .
Type: System.String
The name of the form field to return.
이것은 생성하는 최종 html이 해당 매개 변수를 선택 입력의 이름으로 사용함을 의미합니다. 하지만 실제로는 그 이상을 의미합니다.
디자이너는 사용자가보기 모델을 사용하여 드롭 다운 목록을 표시하고 동일한 보기 모델로 다시 게시 할 것이라고 가정합니다 . 그러나 많은 경우에 우리는 그 가정을 실제로 따르지 않습니다.
위의 예를 사용하십시오.
public class Person {
public int Id { get; set; }
public string Name { get; set; }
}
가정을 따르면이 드롭 다운 목록 관련 뷰에 대한 뷰 모델을 정의해야합니다.
public class PersonsSelectViewModel{
public string SelectedPersonId,
public List<SelectListItem> Persons;
}
다시 게시 할 때 선택한 값만 다시 게시되므로 모델의 속성 SelectedPersonId에 다시 게시해야한다고 가정합니다. 즉, Html.DropDownList의 첫 번째 매개 변수 이름 은 ‘SelectedPersonId’여야합니다. 따라서 디자이너는 뷰에 모델 뷰를 표시 할 때 모델의 속성 SelectedPersonId가 해당 드롭 다운 목록의 기본값을 유지해야한다고 생각합니다. List <SelectListItem> Persons가 이미 Selected 플래그를 설정하여 선택 / 기본값을 표시한다고 생각하더라도 tml.DropDownList는 실제로이를 무시하고 고유 한 IEnumerable <SelectListItem>을 다시 빌드하고 이름에 따라 기본 / 선택된 항목을 설정합니다.
다음은 asp.net mvc의 코드입니다.
private static MvcHtmlString SelectInternal(this HtmlHelper htmlHelper, ModelMetadata metadata,
string optionLabel, string name, IEnumerable<SelectListItem> selectList, bool allowMultiple,
IDictionary<string, object> htmlAttributes)
{
...
bool usedViewData = false;
// If we got a null selectList, try to use ViewData to get the list of items.
if (selectList == null)
{
selectList = htmlHelper.GetSelectData(name);
usedViewData = true;
}
object defaultValue = (allowMultiple) ? htmlHelper.GetModelStateValue(fullName, typeof(string[])) : htmlHelper.GetModelStateValue(fullName, typeof(string));
// If we haven't already used ViewData to get the entire list of items then we need to
// use the ViewData-supplied value before using the parameter-supplied value.
if (defaultValue == null && !String.IsNullOrEmpty(name))
{
if (!usedViewData)
{
defaultValue = htmlHelper.ViewData.Eval(name);
}
else if (metadata != null)
{
defaultValue = metadata.Model;
}
}
if (defaultValue != null)
{
selectList = GetSelectListWithDefaultValue(selectList, defaultValue, allowMultiple);
}
...
return tagBuilder.ToMvcHtmlString(TagRenderMode.Normal);
}
따라서 코드는 실제로 더 나아갔습니다. 모델에서 이름을 조회 할뿐만 아니라 뷰 데이터에서도 이름을 찾으면 selectList를 다시 빌드하고 원래 Selected를 무시합니다.
문제는 많은 경우에 우리는 실제로 그렇게 사용하지 않는다는 것입니다. 우리는 하나 / 여러 항목이 선택된 selectList를 true로 설정하기를 원합니다.
물론 솔루션은 간단합니다. 모델이나 뷰 데이터에없는 이름을 사용하십시오. 일치하는 항목을 찾을 수없는 경우 원래 selectList를 사용하고 원래 Selected가 적용됩니다.
하지만 여전히 mvc가 조건을 하나 더 추가하여 개선해야한다고 생각합니다.
if ((defaultValue != null) && (!selectList.Any(i=>i.Selected)))
{
selectList = GetSelectListWithDefaultValue(selectList, defaultValue, allowMultiple);
}
원래 selectList에 이미 하나의 Selected가있는 경우이를 무시하는 이유는 무엇입니까?
내 생각뿐입니다.
답변
이전 MVC 3 게시물의 코드는 작동하지 않지만 좋은 시작입니다. 내가 고칠 게. 이 코드를 테스트했으며 MVC 3 Razor C #에서 작동합니다.이 코드는 ViewModel 패턴을 사용하여 List<SelectListItem>
.
모델 클래스
public class Product
{
public string Name { get; set; }
public decimal Price { get; set; }
}
ViewModel 클래스
using System.Web.Mvc;
public class ProductListviewModel
{
public List<SelectListItem> Products { get; set; }
}
컨트롤러 방법
public ViewResult List()
{
var productList = new List<SelectListItem>();
foreach (Product p in Products)
{
productList.Add(new SelectListItem
{
Value = p.ProductId.ToString(),
Text = "Product: " + p.Name + " " + p.Price.ToString(),
// To set the selected item use the following code
// Note: you should not set every item to selected
Selected = true
});
}
ProductListViewModel productListVM = new ProductListViewModeld();
productListVM.Products = productList;
return View(productListVM);
}
보기
@model MvcApp.ViewModels.ProductListViewModel
@using (Html.BeginForm())
{
@Html.DropDownList("Products", Model.Products)
}
HTML 출력은 다음과 같습니다.
<select id="Products" name="Products">
<option value="3">Product: Widget 10.00</option>
<option value="4">Product: Gadget 5.95</option>
</select>
출력 형식에 따라 다릅니다. 이게 도움이 되길 바란다. 코드가 작동합니다.
답변
선택한 항목에 대한 모델이 아닌 ViewData 만 확인하므로 SelectExtensions 클래스의 버그로 보입니다. 따라서 트릭은 모델에서 선택한 항목을 속성 이름으로 ViewData 컬렉션으로 복사하는 것입니다.
이것은 MVC 포럼에서 제공 한 답변에서 가져온 것입니다. 또한 Kazi의 DropDownList 속성 을 사용 하는 블로그 게시물 에 더 완전한 답변이 있습니다 .
주어진 모델
public class ArticleType
{
public Guid Id { get; set; }
public string Description { get; set; }
}
public class Article
{
public Guid Id { get; set; }
public string Name { get; set; }
public ArticleType { get; set; }
}
및 기본 뷰 모델
public class ArticleModel
{
public Guid Id { get; set; }
public string Name { get; set; }
[UIHint("DropDownList")]
public Guid ArticleType { get; set; }
}
그런 다음 다음과 같이 DropDownList 편집기 템플릿을 작성합니다.
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<script runat="server">
IEnumerable<SelectListItem> GetSelectList()
{
var metaData = ViewData.ModelMetadata;
if (metaData == null)
{
return null;
}
var selected = Model is SelectListItem ? ((SelectListItem) Model).Value : Model.ToString();
ViewData[metaData.PropertyName] = selected;
var key = metaData.PropertyName + "List";
return (IEnumerable<SelectListItem>)ViewData[key];
}
</script>
<%= Html.DropDownList(null, GetSelectList()) %>
이것은보기 모델의 ArticleType을 SelectListItem으로 변경하는 경우에도 작동하지만 Kazi의 블로그에 따라 유형 변환기를 구현하고 바인더가이를 단순 유형으로 처리하도록 등록해야합니다.
컨트롤러에서 우리는 …
public ArticleController
{
...
public ActionResult Edit(int id)
{
var entity = repository.FindOne<Article>(id);
var model = builder.Convert<ArticleModel>(entity);
var types = repository.FindAll<ArticleTypes>();
ViewData["ArticleTypeList"] = builder.Convert<SelectListItem>(types);
return VIew(model);
}
...
}
답변
문제는 드롭 박스가 적어도 ASP.NET MVC2 디자인이 기대하는 방식으로 목록 박스와 동일하게 작동하지 않는다는 것입니다. 드롭 박스는 여러 값을 선택할 수 있으므로 드롭 박스는 0 개 또는 1 개의 값만 허용합니다. 따라서 HTML에 엄격하므로 해당 값은 “선택됨”플래그로 옵션 목록에있는 것이 아니라 입력 자체에 있어야합니다.
다음 예를 참조하십시오.
<select id="combo" name="combo" value="id2">
<option value="id1">This is option 1</option>
<option value="id2" selected="selected">This is option 2</option>
<option value="id3">This is option 3</option>
</select>
<select id="listbox" name="listbox" multiple>
<option value="id1">This is option 1</option>
<option value="id2" selected="selected">This is option 2</option>
<option value="id3">This is option 3</option>
</select>
콤보에는 옵션이 선택되어 있지만 값 속성이 설정되어 있습니다. 따라서 ASP.NET MVC2가 드롭 박스를 렌더링하고 특정 값 (예 : 기본값 등)을 선택하도록하려면 다음과 같이 렌더링에 값을 지정해야합니다.
// in my view
<%=Html.DropDownList("UserId", selectListItems /* (SelectList)ViewData["UserId"]*/, new { @Value = selectedUser.Id } /* Your selected value as an additional HTML attribute */)%>