드롭 다운 목록 .NET MVC에서 optgroup을 지원합니까?
프로그래밍 방식으로 드롭 다운 목록을 만드는 이 질문에서 계속해서 내 목록에도 여러 optgroup
목록이 있기를 바랍니다. 현재 가능합니까?
selectList를 dropDownList에 전달해야한다는 것을 알고 있지만 selectList에 텍스트, 값, optgroup을 추가하는 방법을 모릅니다.
최종 결과가 생성되기를 원합니다.
<option value="">Please select</option>
<optgroup label="Option A">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</optgroup>
<optgroup label="Option B">
<option value="a">A</option>
<option value="b">B</option>
<option value="c">C</option>
</optgroup>
</option>
www.codeplex.com/aspnet 의 코드를 살펴보면 SelectList 또는 DropDownList 확장 메서드가 선택에서 OptGroup 사용을 지원하지 않는 것으로 보입니다. 자체 확장 메서드를 작성하고 SelectListItem을 확장하여 그룹화를 포함하거나 마크 업에서 수동으로 선택을 생성해야하는 것 같습니다.
내 확장은 조금 더 복잡하지만 원래 DropDownList가 가지고있는 것처럼 모든 오버로드가 있습니다.
실제로 저는 DropDownList를 그룹으로 생성하고 jDoubleSelect의 도움으로 두 개의 결합 된 선택으로 변환 할 수 있도록 특별히 만들었습니다.
using System;using System.Collections;using System.Collections.Generic;using System.Globalization; using System.Linq;using System.Linq.Expressions;using System.Text; using System.Web;using System.Web.Mvc;using System.Web.Routing;
public class GroupedSelectListItem : SelectListItem
{
public string GroupKey { get; set; }
public string GroupName { get; set; }
}
public static class HtmlHelpers
{
public static MvcHtmlString DropDownGroupList(this HtmlHelper htmlHelper, string name)
{
return DropDownListHelper(htmlHelper, name, null, null, null);
}
public static MvcHtmlString DropDownGroupList(this HtmlHelper htmlHelper, string name, IEnumerable<GroupedSelectListItem> selectList)
{
return DropDownListHelper(htmlHelper, name, selectList, null, null);
}
public static MvcHtmlString DropDownGroupList(this HtmlHelper htmlHelper, string name, string optionLabel)
{
return DropDownListHelper(htmlHelper, name, null, optionLabel, null);
}
public static MvcHtmlString DropDownGroupList(this HtmlHelper htmlHelper, string name, IEnumerable<GroupedSelectListItem> selectList, IDictionary<string, object> htmlAttributes)
{
return DropDownListHelper(htmlHelper, name, selectList, null, htmlAttributes);
}
public static MvcHtmlString DropDownGroupList(this HtmlHelper htmlHelper, string name, IEnumerable<GroupedSelectListItem> selectList, object htmlAttributes)
{
return DropDownListHelper(htmlHelper, name, selectList, null, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
}
public static MvcHtmlString DropDownGroupList(this HtmlHelper htmlHelper, string name, IEnumerable<GroupedSelectListItem> selectList, string optionLabel)
{
return DropDownListHelper(htmlHelper, name, selectList, optionLabel, null);
}
public static MvcHtmlString DropDownGroupList(this HtmlHelper htmlHelper, string name, IEnumerable<GroupedSelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes)
{
return DropDownListHelper(htmlHelper, name, selectList, optionLabel, htmlAttributes);
}
public static MvcHtmlString DropDownGroupList(this HtmlHelper htmlHelper, string name, IEnumerable<GroupedSelectListItem> selectList, string optionLabel, object htmlAttributes)
{
return DropDownListHelper(htmlHelper, name, selectList, optionLabel, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
}
public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<GroupedSelectListItem> selectList)
{
return DropDownGroupListFor(htmlHelper, expression, selectList, null /* optionLabel */, null /* htmlAttributes */);
}
public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<GroupedSelectListItem> selectList, object htmlAttributes)
{
return DropDownGroupListFor(htmlHelper, expression, selectList, null /* optionLabel */, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
}
public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<GroupedSelectListItem> selectList, IDictionary<string, object> htmlAttributes)
{
return DropDownGroupListFor(htmlHelper, expression, selectList, null /* optionLabel */, htmlAttributes);
}
public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<GroupedSelectListItem> selectList, string optionLabel)
{
return DropDownGroupListFor(htmlHelper, expression, selectList, optionLabel, null /* htmlAttributes */);
}
public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<GroupedSelectListItem> selectList, string optionLabel, object htmlAttributes)
{
return DropDownGroupListFor(htmlHelper, expression, selectList, optionLabel, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
}
public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<GroupedSelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes)
{
if (expression == null)
{
throw new ArgumentNullException("expression");
}
return DropDownListHelper(htmlHelper, ExpressionHelper.GetExpressionText(expression), selectList, optionLabel, htmlAttributes);
}
private static MvcHtmlString DropDownListHelper(HtmlHelper htmlHelper, string expression, IEnumerable<GroupedSelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes)
{
return SelectInternal(htmlHelper, optionLabel, expression, selectList, false /* allowMultiple */, htmlAttributes);
}
// Helper methods
private static IEnumerable<GroupedSelectListItem> GetSelectData(this HtmlHelper htmlHelper, string name)
{
object o = null;
if (htmlHelper.ViewData != null)
{
o = htmlHelper.ViewData.Eval(name);
}
if (o == null)
{
throw new InvalidOperationException(
String.Format(
CultureInfo.CurrentCulture,
"Missing Select Data"));
}
var selectList = o as IEnumerable<GroupedSelectListItem>;
if (selectList == null)
{
throw new InvalidOperationException(
String.Format(
CultureInfo.CurrentCulture,
"Wrong Select DataType"));
}
return selectList;
}
internal static string ListItemToOption(GroupedSelectListItem item)
{
var builder = new TagBuilder("option")
{
InnerHtml = HttpUtility.HtmlEncode(item.Text)
};
if (item.Value != null)
{
builder.Attributes["value"] = item.Value;
}
if (item.Selected)
{
builder.Attributes["selected"] = "selected";
}
return builder.ToString(TagRenderMode.Normal);
}
private static MvcHtmlString SelectInternal(this HtmlHelper htmlHelper, string optionLabel, string name, IEnumerable<GroupedSelectListItem> selectList, bool allowMultiple, IDictionary<string, object> htmlAttributes)
{
name = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
if (String.IsNullOrEmpty(name))
{
throw new ArgumentException("Null Or Empty", "name");
}
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(name, typeof(string[])) : htmlHelper.GetModelStateValue(name, 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 (!usedViewData)
{
if (defaultValue == null)
{
defaultValue = htmlHelper.ViewData.Eval(name);
}
}
if (defaultValue != null)
{
var defaultValues = (allowMultiple) ? defaultValue as IEnumerable : new[] { defaultValue };
var values = from object value in defaultValues select Convert.ToString(value, CultureInfo.CurrentCulture);
var selectedValues = new HashSet<string>(values, StringComparer.OrdinalIgnoreCase);
var newSelectList = new List<GroupedSelectListItem>();
foreach (var item in selectList)
{
item.Selected = (item.Value != null) ? selectedValues.Contains(item.Value) : selectedValues.Contains(item.Text);
newSelectList.Add(item);
}
selectList = newSelectList;
}
// Convert each ListItem to an <option> tag
var listItemBuilder = new StringBuilder();
// Make optionLabel the first item that gets rendered.
if (optionLabel != null)
{
listItemBuilder.AppendLine(ListItemToOption(new GroupedSelectListItem { Text = optionLabel, Value = String.Empty, Selected = false }));
}
foreach (var group in selectList.GroupBy(i => i.GroupKey))
{
string groupName = selectList.Where(i => i.GroupKey == group.Key).Select(it => it.GroupName).FirstOrDefault();
listItemBuilder.AppendLine(string.Format("<optgroup label=\"{0}\" value=\"{1}\">", groupName, group.Key));
foreach (GroupedSelectListItem item in group)
{
listItemBuilder.AppendLine(ListItemToOption(item));
}
listItemBuilder.AppendLine("</optgroup>");
}
var tagBuilder = new TagBuilder("select")
{
InnerHtml = listItemBuilder.ToString()
};
tagBuilder.MergeAttributes(htmlAttributes);
tagBuilder.MergeAttribute("name", name, true /* replaceExisting */);
tagBuilder.GenerateId(name);
if (allowMultiple)
{
tagBuilder.MergeAttribute("multiple", "multiple");
}
// If there are any errors for a named field, we add the css attribute.
ModelState modelState;
if (htmlHelper.ViewData.ModelState.TryGetValue(name, out modelState))
{
if (modelState.Errors.Count > 0)
{
tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
}
}
return MvcHtmlString.Create(tagBuilder.ToString());
}
internal static object GetModelStateValue(this HtmlHelper helper, string key, Type destinationType)
{
ModelState modelState;
if (helper.ViewData.ModelState.TryGetValue(key, out modelState))
{
if (modelState.Value != null)
{
return modelState.Value.ConvertTo(destinationType, null /* culture */);
}
}
return null;
}
}
이것은 버전 5.2의 ASP.Net MVC에 추가되었으며 이제 기본 제공됩니다.
SelectListItem 의 Group 속성을 사용하면 각 항목에 대한 그룹을 지정할 수 있습니다.
새 SelectList 생성자 를 사용하면 제공된 항목 목록에 그룹 제목이 포함 된 필드의 이름을 제공 할 수도 있습니다.
HtmlHelper DropDownList 및 DropDownListFor 메서드는 이제 항목 목록에 포함 된 그룹을 기반으로 optgroup 요소를 생성합니다.
쉬운!
나는 이것을 위해 확장을 작성했다.
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Routing;
namespace System.Web.Mvc.Html
{
public static class GroupDropListExtensions
{
public static string GroupDropList(this HtmlHelper helper, string name, IEnumerable<GroupDropListItem> data, string SelectedValue, object htmlAttributes)
{
if (data == null && helper.ViewData != null)
data = helper.ViewData.Eval(name) as IEnumerable<GroupDropListItem>;
if (data == null) return string.Empty;
var select = new TagBuilder("select");
if (htmlAttributes != null)
select.MergeAttributes(new RouteValueDictionary(htmlAttributes));
select.GenerateId(name);
var optgroupHtml = new StringBuilder();
var groups = data.ToList();
foreach (var group in data)
{
var groupTag = new TagBuilder("optgroup");
groupTag.Attributes.Add("label", helper.Encode( group.Name));
var optHtml = new StringBuilder();
foreach (var item in group.Items)
{
var option = new TagBuilder("option");
option.Attributes.Add("value", helper.Encode(item.Value));
if (SelectedValue != null && item.Value == SelectedValue)
option.Attributes.Add("selected", "selected");
option.InnerHtml = helper.Encode(item.Text);
optHtml.AppendLine(option.ToString(TagRenderMode.Normal));
}
groupTag.InnerHtml = optHtml.ToString();
optgroupHtml.AppendLine(groupTag.ToString(TagRenderMode.Normal));
}
select.InnerHtml = optgroupHtml.ToString();
return select.ToString(TagRenderMode.Normal);
}
}
public class GroupDropListItem
{
public string Name { get; set; }
public List<OptionItem> Items { get; set; }
}
public class OptionItem
{
public string Text { get; set; }
public string Value { get; set; }
}
}
클라이언트 유효성 검사에 대한 데이터 주석이 누락 되었습니까?
위의 Chrno Love의 질문에 대한 대답으로 Serge Zab의 솔루션에 추가-MVC3 클라이언트 측 유효성 검사 속성에 대한 Milimetric의 수정은 동일한보기에서 드롭 다운 모음을 사용할 때 다음과 같습니다.
public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>>
expression,
IEnumerable<GroupedSelectListItem>
selectList, string optionLabel,
IDictionary<string, object> htmlAttributes)
{
if (expression == null)
{
throw new ArgumentNullException("expression");
}
// fixing clientside validation attributes
// http://stackoverflow.com/questions/4799958/asp-net-mvc-3-unobtrusive-client-validation-does-not-work-with-drop-down-lists/8102022#8102022
var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
var mergedAttributes =
htmlHelper.GetUnobtrusiveValidationAttributes(ExpressionHelper.GetExpressionText(expression), metadata);
if (htmlAttributes != null)
{
foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(htmlAttributes))
{
object value = descriptor.GetValue(htmlAttributes);
mergedAttributes.Add(descriptor.Name, value);
}
}
//return DropDownListHelper(htmlHelper, ExpressionHelper.GetExpressionText(expression), selectList, optionLabel, htmlAttributes);
return DropDownListHelper(htmlHelper, ExpressionHelper.GetExpressionText(expression), selectList, optionLabel, mergedAttributes);
}
Serge Zab의 대답은 정확히 내가 찾던 것이었다. 다이 하드 VB 프로그래머이기 때문에 다음 VB 모듈에 이식했습니다.
'based on Serge Zab's answer on http://stackoverflow.com/questions/607188/support-for-optgroup-in-dropdownlist-net-mvc
Imports System.Collections
Imports System.Collections.Generic
Imports System.Globalization
Imports System.Linq
Imports System.Linq.Expressions
Imports System.Text
Imports System.Web
Imports System.Web.Mvc
Imports System.Web.Routing
Public Class GroupedSelectListItem
Inherits SelectListItem
Public Property GroupKey() As String
Get
Return m_GroupKey
End Get
Set(value As String)
m_GroupKey = Value
End Set
End Property
Private m_GroupKey As String
Public Property GroupName() As String
Get
Return m_GroupName
End Get
Set(value As String)
m_GroupName = Value
End Set
End Property
Private m_GroupName As String
End Class
Public Module HtmlHelpers
<System.Runtime.CompilerServices.Extension> _
Public Function DropDownGroupList(htmlHelper As HtmlHelper, name As String) As MvcHtmlString
Return DropDownListHelper(htmlHelper, name, Nothing, Nothing, Nothing)
End Function
<System.Runtime.CompilerServices.Extension> _
Public Function DropDownGroupList(htmlHelper As HtmlHelper, name As String, selectList As IEnumerable(Of GroupedSelectListItem)) As MvcHtmlString
Return DropDownListHelper(htmlHelper, name, selectList, Nothing, Nothing)
End Function
<System.Runtime.CompilerServices.Extension> _
Public Function DropDownGroupList(htmlHelper As HtmlHelper, name As String, optionLabel As String) As MvcHtmlString
Return DropDownListHelper(htmlHelper, name, Nothing, optionLabel, Nothing)
End Function
<System.Runtime.CompilerServices.Extension> _
Public Function DropDownGroupList(htmlHelper As HtmlHelper, name As String, selectList As IEnumerable(Of GroupedSelectListItem), htmlAttributes As IDictionary(Of String, Object)) As MvcHtmlString
Return DropDownListHelper(htmlHelper, name, selectList, Nothing, htmlAttributes)
End Function
<System.Runtime.CompilerServices.Extension> _
Public Function DropDownGroupList(htmlHelper As HtmlHelper, name As String, selectList As IEnumerable(Of GroupedSelectListItem), htmlAttributes As Object) As MvcHtmlString
Return DropDownListHelper(htmlHelper, name, selectList, Nothing, New RouteValueDictionary(htmlAttributes))
End Function
<System.Runtime.CompilerServices.Extension> _
Public Function DropDownGroupList(htmlHelper As HtmlHelper, name As String, selectList As IEnumerable(Of GroupedSelectListItem), optionLabel As String) As MvcHtmlString
Return DropDownListHelper(htmlHelper, name, selectList, optionLabel, Nothing)
End Function
<System.Runtime.CompilerServices.Extension> _
Public Function DropDownGroupList(htmlHelper As HtmlHelper, name As String, selectList As IEnumerable(Of GroupedSelectListItem), optionLabel As String, htmlAttributes As IDictionary(Of String, Object)) As MvcHtmlString
Return DropDownListHelper(htmlHelper, name, selectList, optionLabel, htmlAttributes)
End Function
<System.Runtime.CompilerServices.Extension> _
Public Function DropDownGroupList(htmlHelper As HtmlHelper, name As String, selectList As IEnumerable(Of GroupedSelectListItem), optionLabel As String, htmlAttributes As Object) As MvcHtmlString
Return DropDownListHelper(htmlHelper, name, selectList, optionLabel, New RouteValueDictionary(htmlAttributes))
End Function
<System.Runtime.CompilerServices.Extension> _
Public Function DropDownGroupListFor(Of TModel, TProperty)(htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TProperty)), selectList As IEnumerable(Of GroupedSelectListItem)) As MvcHtmlString
' optionLabel
' htmlAttributes
Return DropDownGroupListFor(htmlHelper, expression, selectList, Nothing, Nothing)
End Function
<System.Runtime.CompilerServices.Extension> _
Public Function DropDownGroupListFor(Of TModel, TProperty)(htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TProperty)), selectList As IEnumerable(Of GroupedSelectListItem), htmlAttributes As Object) As MvcHtmlString
' optionLabel
Return DropDownGroupListFor(htmlHelper, expression, selectList, Nothing, New RouteValueDictionary(htmlAttributes))
End Function
<System.Runtime.CompilerServices.Extension> _
Public Function DropDownGroupListFor(Of TModel, TProperty)(htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TProperty)), selectList As IEnumerable(Of GroupedSelectListItem), htmlAttributes As IDictionary(Of String, Object)) As MvcHtmlString
' optionLabel
Return DropDownGroupListFor(htmlHelper, expression, selectList, Nothing, htmlAttributes)
End Function
<System.Runtime.CompilerServices.Extension> _
Public Function DropDownGroupListFor(Of TModel, TProperty)(htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TProperty)), selectList As IEnumerable(Of GroupedSelectListItem), optionLabel As String) As MvcHtmlString
' htmlAttributes
Return DropDownGroupListFor(htmlHelper, expression, selectList, optionLabel, Nothing)
End Function
<System.Runtime.CompilerServices.Extension> _
Public Function DropDownGroupListFor(Of TModel, TProperty)(htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TProperty)), selectList As IEnumerable(Of GroupedSelectListItem), optionLabel As String, htmlAttributes As Object) As MvcHtmlString
Return DropDownGroupListFor(htmlHelper, expression, selectList, optionLabel, New RouteValueDictionary(htmlAttributes))
End Function
<System.Runtime.CompilerServices.Extension> _
Public Function DropDownGroupListFor(Of TModel, TProperty)(htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TProperty)), selectList As IEnumerable(Of GroupedSelectListItem), optionLabel As String, htmlAttributes As IDictionary(Of String, Object)) As MvcHtmlString
If expression Is Nothing Then
Throw New ArgumentNullException("expression")
End If
Return DropDownListHelper(htmlHelper, ExpressionHelper.GetExpressionText(expression), selectList, optionLabel, htmlAttributes)
End Function
Private Function DropDownListHelper(htmlHelper As HtmlHelper, expression As String, selectList As IEnumerable(Of GroupedSelectListItem), optionLabel As String, htmlAttributes As IDictionary(Of String, Object)) As MvcHtmlString
' allowMultiple
Return SelectInternal(htmlHelper, optionLabel, expression, selectList, False, htmlAttributes)
End Function
' Helper methods
<System.Runtime.CompilerServices.Extension> _
Private Function GetSelectData(htmlHelper As HtmlHelper, name As String) As IEnumerable(Of GroupedSelectListItem)
Dim o As Object = Nothing
If htmlHelper.ViewData IsNot Nothing Then
o = htmlHelper.ViewData.Eval(name)
End If
If o Is Nothing Then
Throw New InvalidOperationException([String].Format(CultureInfo.CurrentCulture, "Missing Select Data", name, "IEnumerable<GroupedSelectListItem>"))
End If
Dim selectList As IEnumerable(Of GroupedSelectListItem) = TryCast(o, IEnumerable(Of GroupedSelectListItem))
If selectList Is Nothing Then
Throw New InvalidOperationException([String].Format(CultureInfo.CurrentCulture, "Wrong Select DataType", name, o.[GetType]().FullName, "IEnumerable<GroupedSelectListItem>"))
End If
Return selectList
End Function
Friend Function ListItemToOption(item As GroupedSelectListItem) As String
Dim builder As New TagBuilder("option") With { _
.InnerHtml = HttpUtility.HtmlEncode(item.Text) _
}
If item.Value IsNot Nothing Then
builder.Attributes("value") = item.Value
End If
If item.Selected Then
builder.Attributes("selected") = "selected"
End If
Return builder.ToString(TagRenderMode.Normal)
End Function
<System.Runtime.CompilerServices.Extension> _
Private Function SelectInternal(htmlHelper__1 As HtmlHelper, optionLabel As String, name As String, selectList As IEnumerable(Of GroupedSelectListItem), allowMultiple As Boolean, htmlAttributes As IDictionary(Of String, Object)) As MvcHtmlString
name = htmlHelper__1.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name)
If [String].IsNullOrEmpty(name) Then
Throw New ArgumentException("Null Or Empty", "name")
End If
Dim usedViewData As Boolean = False
' If we got a null selectList, try to use ViewData to get the list of items.
If selectList Is Nothing Then
selectList = htmlHelper__1.GetSelectData(name)
usedViewData = True
End If
Dim defaultValue As Object = If((allowMultiple), htmlHelper__1.GetModelStateValue(name, GetType(String())), htmlHelper__1.GetModelStateValue(name, GetType(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 Not usedViewData Then
If defaultValue Is Nothing Then
defaultValue = htmlHelper__1.ViewData.Eval(name)
End If
End If
If defaultValue IsNot Nothing Then
Dim defaultValues As IEnumerable = If((allowMultiple), TryCast(defaultValue, IEnumerable), New String() {defaultValue})
Dim values As IEnumerable(Of String) = From value In defaultValues Select (Convert.ToString(value, CultureInfo.CurrentCulture))
Dim selectedValues As New HashSet(Of String)(values, StringComparer.OrdinalIgnoreCase)
Dim newSelectList As New List(Of GroupedSelectListItem)()
For Each item As GroupedSelectListItem In selectList
item.Selected = If((item.Value IsNot Nothing), selectedValues.Contains(item.Value), selectedValues.Contains(item.Text))
newSelectList.Add(item)
Next
selectList = newSelectList
End If
' Convert each ListItem to an <option> tag
Dim listItemBuilder As New StringBuilder()
' Make optionLabel the first item that gets rendered.
If optionLabel IsNot Nothing Then
listItemBuilder.AppendLine(ListItemToOption(New GroupedSelectListItem() With { _
.Text = optionLabel, _
.Value = [String].Empty, _
.Selected = False _
}))
End If
For Each group As Object In selectList.GroupBy(Function(i) i.GroupKey)
Dim groupName As String = selectList.Where(Function(i) i.GroupKey = group.Key).[Select](Function(it) it.GroupName).FirstOrDefault()
listItemBuilder.AppendLine(String.Format("<optgroup label=""{0}"" value=""{1}"">", groupName, group.Key))
For Each item As GroupedSelectListItem In group
listItemBuilder.AppendLine(ListItemToOption(item))
Next
listItemBuilder.AppendLine("</optgroup>")
Next
Dim tagBuilder As New TagBuilder("select") With { _
.InnerHtml = listItemBuilder.ToString() _
}
TagBuilder.MergeAttributes(htmlAttributes)
' replaceExisting
TagBuilder.MergeAttribute("name", name, True)
TagBuilder.GenerateId(name)
If allowMultiple Then
TagBuilder.MergeAttribute("multiple", "multiple")
End If
' If there are any errors for a named field, we add the css attribute.
Dim modelState As ModelState = Nothing
If htmlHelper__1.ViewData.ModelState.TryGetValue(name, modelState) Then
If modelState.Errors.Count > 0 Then
TagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName)
End If
End If
Return MvcHtmlString.Create(TagBuilder.ToString())
End Function
<System.Runtime.CompilerServices.Extension> _
Friend Function GetModelStateValue(helper As HtmlHelper, key As String, destinationType As Type) As Object
Dim modelState As ModelState = Nothing
If helper.ViewData.ModelState.TryGetValue(key, modelState) Then
If modelState.Value IsNot Nothing Then
' culture
Return modelState.Value.ConvertTo(destinationType, Nothing)
End If
End If
Return Nothing
End Function
End Module
잘 작동하는 @Serge Zab 솔루션을 시도했지만 약간의 검사 후 문제를 발견 한 후 눈에 잘 띄지 않는 유효성 검사에 문제가있었습니다.
TagBuilder를 만든 직후 Jquery 유효성 검사를 실행하려는 경우 select 요소에서 누락 된 일부 필수 속성이있는 것 같습니다.
TagBuilder tagBuilder = new TagBuilder("select");
다음 속성 추가
tagBuilder.MergeAttribute("data-val", "true",true);
tagBuilder.MergeAttribute("data-val-required", "your validation message", true)
눈에 잘 띄지 않는 유효성 검사가 실행됩니다.
Serge Zab answer 에서, 같은 데이터 속성 data_valuename
은 올바른 형식으로 마진하지 않습니다 data-valuename
.
I replaced code tagBuilder.MergeAttributes(htmlAttributes);
in SelectInternal
method to this
foreach (var htmlAttribute in htmlAttributes)
{
tagBuilder.MergeAttribute(
htmlAttribute.Key.Replace('_', '-'),
(string)htmlAttribute.Value
);
}
Just a note on using Serge's extension to create more than one select list on the same form. I was having problems getting the second select list to apply the groups, and when I examined the html being generated I realized both had been given the same id. To fix this, go into the SelectInternal function in serge's extension and comment out/delete the following two lines:
tagBuilder.MergeAttribute("name", name, true /* replaceExisting */); tagBuilder.GenerateId(name);
Alternatively you can just pass unique id's to each (though the DropDownGroupListFor doesn't take the 'string name' parameter so you'll have to add an overload that does)
I needed a solution to handle a multiple selection with optgroup, and I used Serge Zab solution. I've just two comments about it (too long for a comment).
Despite his claims, his solution does not support all existing overloads of DropDownListFor, since it doesn't support MultiSelectList or SelectList, oftenly used in models. But that's not hard to add these.
His solution was not working for me for Multiple selection to initialize selected/not selected items from model : the initial values were not affected. I've just modified the following method :
private static MvcHtmlString DropDownListHelper(...) { return SelectInternal(htmlHelper, optionLabel, expression, selectList, false /* allowMultiple */, htmlAttributes); }
To this :
private static MvcHtmlString DropDownListHelper(HtmlHelper htmlHelper, string expression, IEnumerable<GroupedSelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes)
{
bool allowMultiple = htmlAttributes.ContainsKey("multiple");
return SelectInternal(htmlHelper, optionLabel, expression, selectList, allowMultiple, htmlAttributes);
}
And it worked as expected. Of course the multiple attribute must be defined : @Html.DropDownGroupListFor(m => m.Selected, Model.Values, new { multiple = "multiple" })
Thanks to Serge for his answer.
참고URL : https://stackoverflow.com/questions/607188/support-for-optgroup-in-dropdownlist-net-mvc
'Programing' 카테고리의 다른 글
최대 절전 모드 제한 및 / 또는 조합 (0) | 2020.11.23 |
---|---|
반응 형 입력 필드 비활성화 (0) | 2020.11.23 |
readonly =“true”와 readonly =“readonly”의 차이점은 무엇입니까? (0) | 2020.11.23 |
Ruby JSON 구문 분석으로 해시 키 변경 (0) | 2020.11.23 |
줌 제어 및 스트리트 뷰가 내 Google지도에 표시되지 않습니까? (0) | 2020.11.23 |