드롭 다운 목록 제어
옵션 그룹을 렌더링 할 수있는 asp.net (3.5)에 대한 드롭 다운 목록 컨트롤을 추천 할 수 있습니까? 감사
나는 과거에 표준 컨트롤을 사용했으며, 특정 위치에서 <optgroup>을 렌더링 할 수 있도록 기본 동작을 재정의 하는 간단한 ControlAdapter 를 추가했습니다 . 추가 기능이 방해가되지 않기 때문에 특별한 동작이 필요하지 않은 컨트롤이있는 경우에도 잘 작동합니다.
이것은 특정 목적을위한 것이며 .Net 2.0으로 작성되었으므로 귀하에게 적합하지 않을 수 있지만 최소한 시작점을 제공해야합니다. 또한 프로젝트에서 .browserfile을 사용하여 연결해야합니다 (예는 게시물 끝 부분 참조).
'This codes makes the dropdownlist control recognize items with "--"
'for the label or items with an OptionGroup attribute and render them
'as <optgroup> instead of <option>.
Public Class DropDownListAdapter
Inherits System.Web.UI.WebControls.Adapters.WebControlAdapter
Protected Overrides Sub RenderContents(ByVal writer As HtmlTextWriter)
Dim list As DropDownList = Me.Control
Dim currentOptionGroup As String
Dim renderedOptionGroups As New Generic.List(Of String)
For Each item As ListItem In list.Items
Page.ClientScript.RegisterForEventValidation(list.UniqueID, item.Value)
If item.Attributes("OptionGroup") IsNot Nothing Then
'The item is part of an option group
currentOptionGroup = item.Attributes("OptionGroup")
If Not renderedOptionGroups.Contains(currentOptionGroup) Then
'the header was not written- do that first
'TODO: make this stack-based, so the same option group can be used more than once in longer select element (check the most-recent stack item instead of anything in the list)
If (renderedOptionGroups.Count > 0) Then
RenderOptionGroupEndTag(writer) 'need to close previous group
End If
RenderOptionGroupBeginTag(currentOptionGroup, writer)
renderedOptionGroups.Add(currentOptionGroup)
End If
RenderListItem(item, writer)
ElseIf item.Text = "--" Then 'simple separator
RenderOptionGroupBeginTag("--", writer)
RenderOptionGroupEndTag(writer)
Else
'default behavior: render the list item as normal
RenderListItem(item, writer)
End If
Next item
If renderedOptionGroups.Count > 0 Then
RenderOptionGroupEndTag(writer)
End If
End Sub
Private Sub RenderOptionGroupBeginTag(ByVal name As String, ByVal writer As HtmlTextWriter)
writer.WriteBeginTag("optgroup")
writer.WriteAttribute("label", name)
writer.Write(HtmlTextWriter.TagRightChar)
writer.WriteLine()
End Sub
Private Sub RenderOptionGroupEndTag(ByVal writer As HtmlTextWriter)
writer.WriteEndTag("optgroup")
writer.WriteLine()
End Sub
Private Sub RenderListItem(ByVal item As ListItem, ByVal writer As HtmlTextWriter)
writer.WriteBeginTag("option")
writer.WriteAttribute("value", item.Value, True)
If item.Selected Then
writer.WriteAttribute("selected", "selected", False)
End If
For Each key As String In item.Attributes.Keys
writer.WriteAttribute(key, item.Attributes(key))
Next key
writer.Write(HtmlTextWriter.TagRightChar)
HttpUtility.HtmlEncode(item.Text, writer)
writer.WriteEndTag("option")
writer.WriteLine()
End Sub
End Class
다음은 동일한 클래스의 C # 구현입니다.
/* This codes makes the dropdownlist control recognize items with "--"
* for the label or items with an OptionGroup attribute and render them
* as <optgroup> instead of <option>.
*/
public class DropDownListAdapter : WebControlAdapter
{
protected override void RenderContents(HtmlTextWriter writer)
{
//System.Web.HttpContext.Current.Response.Write("here");
var list = (DropDownList)this.Control;
string currentOptionGroup;
var renderedOptionGroups = new List<string>();
foreach (ListItem item in list.Items)
{
Page.ClientScript.RegisterForEventValidation(list.UniqueID, item.Value);
//Is the item part of an option group?
if (item.Attributes["OptionGroup"] != null)
{
currentOptionGroup = item.Attributes["OptionGroup"];
//Was the option header already written, then just render the list item
if (renderedOptionGroups.Contains(currentOptionGroup))
RenderListItem(item, writer);
//The header was not written,do that first
else
{
//Close previous group
if (renderedOptionGroups.Count > 0)
RenderOptionGroupEndTag(writer);
RenderOptionGroupBeginTag(currentOptionGroup, writer);
renderedOptionGroups.Add(currentOptionGroup);
RenderListItem(item, writer);
}
}
//Simple separator
else if (item.Text == "--")
{
RenderOptionGroupBeginTag("--", writer);
RenderOptionGroupEndTag(writer);
}
//Default behavior, render the list item as normal
else
RenderListItem(item, writer);
}
if (renderedOptionGroups.Count > 0)
RenderOptionGroupEndTag(writer);
}
private void RenderOptionGroupBeginTag(string name, HtmlTextWriter writer)
{
writer.WriteBeginTag("optgroup");
writer.WriteAttribute("label", name);
writer.Write(HtmlTextWriter.TagRightChar);
writer.WriteLine();
}
private void RenderOptionGroupEndTag(HtmlTextWriter writer)
{
writer.WriteEndTag("optgroup");
writer.WriteLine();
}
private void RenderListItem(ListItem item, HtmlTextWriter writer)
{
writer.WriteBeginTag("option");
writer.WriteAttribute("value", item.Value, true);
if (item.Selected)
writer.WriteAttribute("selected", "selected", false);
foreach (string key in item.Attributes.Keys)
writer.WriteAttribute(key, item.Attributes[key]);
writer.Write(HtmlTextWriter.TagRightChar);
HttpUtility.HtmlEncode(item.Text, writer);
writer.WriteEndTag("option");
writer.WriteLine();
}
}
내 브라우저 파일 이름은 "App_Browsers \ BrowserFile.browser"이며 다음과 같습니다.
<!--
You can find existing browser definitions at
<windir>\Microsoft.NET\Framework\<ver>\CONFIG\Browsers
-->
<browsers>
<browser refID="Default">
<controlAdapters>
<adapter controlType="System.Web.UI.WebControls.DropDownList"
adapterType="DropDownListAdapter" />
</controlAdapters>
</browser>
</browsers>
이 작업을 수행하기 위해 JQuery를 사용했습니다. 먼저 ListItem
백엔드의 모든 속성에 대해 새 속성을 추가 한 다음 JQuery wrapAll()
메서드 에서 해당 속성을 사용 하여 그룹을 생성했습니다.
씨#:
foreach (ListItem item in ((DropDownList)sender).Items)
{
if (System.Int32.Parse(item.Value) < 5)
item.Attributes.Add("classification", "LessThanFive");
else
item.Attributes.Add("classification", "GreaterThanFive");
}
JQuery :
$(document).ready(function() {
//Create groups for dropdown list
$("select.listsmall option[@classification='LessThanFive']")
.wrapAll("<optgroup label='Less than five'>");
$("select.listsmall option[@classification='GreaterThanFive']")
.wrapAll("<optgroup label='Greater than five'>");
});
감사합니다 Joel! 모두 ... 원하는 경우 여기에 C # 버전이 있습니다.
using System;
using System.Web.UI.WebControls.Adapters;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections.Generic;
using System.Web;
//This codes makes the dropdownlist control recognize items with "--"'
//for the label or items with an OptionGroup attribute and render them'
//as instead of .'
public class DropDownListAdapter : WebControlAdapter
{
protected override void RenderContents(HtmlTextWriter writer)
{
DropDownList list = Control as DropDownList;
string currentOptionGroup;
List renderedOptionGroups = new List();
foreach(ListItem item in list.Items)
{
if (item.Attributes["OptionGroup"] != null)
{
//'The item is part of an option group'
currentOptionGroup = item.Attributes["OptionGroup"];
//'the option header was already written, just render the list item'
if(renderedOptionGroups.Contains(currentOptionGroup))
RenderListItem(item, writer);
else
{
//the header was not written- do that first'
if (renderedOptionGroups.Count > 0)
RenderOptionGroupEndTag(writer); //'need to close previous group'
RenderOptionGroupBeginTag(currentOptionGroup, writer);
renderedOptionGroups.Add(currentOptionGroup);
RenderListItem(item, writer);
}
}
else if (item.Text == "--") //simple separator
{
RenderOptionGroupBeginTag("--", writer);
RenderOptionGroupEndTag(writer);
}
else
{
//default behavior: render the list item as normal'
RenderListItem(item, writer);
}
}
if(renderedOptionGroups.Count > 0)
RenderOptionGroupEndTag(writer);
}
private void RenderOptionGroupBeginTag(string name, HtmlTextWriter writer)
{
writer.WriteBeginTag("optgroup");
writer.WriteAttribute("label", name);
writer.Write(HtmlTextWriter.TagRightChar);
writer.WriteLine();
}
private void RenderOptionGroupEndTag(HtmlTextWriter writer)
{
writer.WriteEndTag("optgroup");
writer.WriteLine();
}
private void RenderListItem(ListItem item, HtmlTextWriter writer)
{
writer.WriteBeginTag("option");
writer.WriteAttribute("value", item.Value, true);
if (item.Selected)
writer.WriteAttribute("selected", "selected", false);
foreach (string key in item.Attributes.Keys)
writer.WriteAttribute(key, item.Attributes[key]);
writer.Write(HtmlTextWriter.TagRightChar);
HttpUtility.HtmlEncode(item.Text, writer);
writer.WriteEndTag("option");
writer.WriteLine();
}
}
위의 코드는 옵션 앞에 optgroup에 대한 종료 태그를 렌더링하므로 그룹화를 제대로 나타내지 않는 마크 업에 추가하여 옵션이 들여 쓰기되지 않습니다. 다음은 Tom의 코드를 약간 수정 한 버전입니다.
public class ExtendedDropDownList : System.Web.UI.WebControls.DropDownList
{
public const string OptionGroupTag = "optgroup";
private const string OptionTag = "option";
protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)
{
ListItemCollection items = this.Items;
int count = items.Count;
string tag;
string optgroupLabel;
if (count > 0)
{
bool flag = false;
string prevOptGroup = null;
for (int i = 0; i < count; i++)
{
tag = OptionTag;
optgroupLabel = null;
ListItem item = items[i];
if (item.Enabled)
{
if (item.Attributes != null && item.Attributes.Count > 0 && item.Attributes[OptionGroupTag] != null)
{
optgroupLabel = item.Attributes[OptionGroupTag];
if (prevOptGroup != optgroupLabel)
{
if (prevOptGroup != null)
{
writer.WriteEndTag(OptionGroupTag);
}
writer.WriteBeginTag(OptionGroupTag);
if (!string.IsNullOrEmpty(optgroupLabel))
{
writer.WriteAttribute("label", optgroupLabel);
}
writer.Write('>');
}
item.Attributes.Remove(OptionGroupTag);
prevOptGroup = optgroupLabel;
}
else
{
if (prevOptGroup != null)
{
writer.WriteEndTag(OptionGroupTag);
}
prevOptGroup = null;
}
writer.WriteBeginTag(tag);
if (item.Selected)
{
if (flag)
{
this.VerifyMultiSelect();
}
flag = true;
writer.WriteAttribute("selected", "selected");
}
writer.WriteAttribute("value", item.Value, true);
if (item.Attributes != null && item.Attributes.Count > 0)
{
item.Attributes.Render(writer);
}
if (optgroupLabel != null)
{
item.Attributes.Add(OptionGroupTag, optgroupLabel);
}
if (this.Page != null)
{
this.Page.ClientScript.RegisterForEventValidation(this.UniqueID, item.Value);
}
writer.Write('>');
HttpUtility.HtmlEncode(item.Text, writer);
writer.WriteEndTag(tag);
writer.WriteLine();
if (i == count - 1)
{
if (prevOptGroup != null)
{
writer.WriteEndTag(OptionGroupTag);
}
}
}
}
}
}
protected override object SaveViewState()
{
object[] state = new object[this.Items.Count + 1];
object baseState = base.SaveViewState();
state[0] = baseState;
bool itemHasAttributes = false;
for (int i = 0; i < this.Items.Count; i++)
{
if (this.Items[i].Attributes.Count > 0)
{
itemHasAttributes = true;
object[] attributes = new object[this.Items[i].Attributes.Count * 2];
int k = 0;
foreach (string key in this.Items[i].Attributes.Keys)
{
attributes[k] = key;
k++;
attributes[k] = this.Items[i].Attributes[key];
k++;
}
state[i + 1] = attributes;
}
}
if (itemHasAttributes)
return state;
return baseState;
}
protected override void LoadViewState(object savedState)
{
if (savedState == null)
return;
if (!(savedState.GetType().GetElementType() == null) &&
(savedState.GetType().GetElementType().Equals(typeof(object))))
{
object[] state = (object[])savedState;
base.LoadViewState(state[0]);
for (int i = 1; i < state.Length; i++)
{
if (state[i] != null)
{
object[] attributes = (object[])state[i];
for (int k = 0; k < attributes.Length; k += 2)
{
this.Items[i - 1].Attributes.Add
(attributes[k].ToString(), attributes[k + 1].ToString());
}
}
}
}
else
{
base.LoadViewState(savedState);
}
}
}
다음과 같이 사용하십시오.
ListItem item1 = new ListItem("option1");
item1.Attributes.Add("optgroup", "CatA");
ListItem item2 = new ListItem("option2");
item2.Attributes.Add("optgroup", "CatA");
ListItem item3 = new ListItem("option3");
item3.Attributes.Add("optgroup", "CatB");
ListItem item4 = new ListItem("option4");
item4.Attributes.Add("optgroup", "CatB");
ListItem item5 = new ListItem("NoOptGroup");
ddlTest.Items.Add(item1);
ddlTest.Items.Add(item2);
ddlTest.Items.Add(item3);
ddlTest.Items.Add(item4);
ddlTest.Items.Add(item5);
다음은 생성 된 마크 업입니다 (보기 쉽도록 들여 쓰기).
<select name="ddlTest" id="Select1">
<optgroup label="CatA">
<option selected="selected" value="option1">option1</option>
<option value="option2">option2</option>
</optgroup>
<optgroup label="CatB">
<option value="option3">option3</option>
<option value="option4">option4</option>
</optgroup>
<option value="NoOptGroup">NoOptGroup</option>
</select>
CodePlex 의 Sharp Pieces 프로젝트 는이 (및 기타 여러 가지) 제어 제한을 해결합니다.
반사경을 사용하여 지원되지 않는 이유를 확인합니다. 이유가 있습니다. ListControl의 render 메서드에는 optgroup을 생성하기위한 조건이 없습니다.
protected internal override void RenderContents(HtmlTextWriter writer)
{
ListItemCollection items = this.Items;
int count = items.Count;
if (count > 0)
{
bool flag = false;
for (int i = 0; i < count; i++)
{
ListItem item = items[i];
if (item.Enabled)
{
writer.WriteBeginTag("option");
if (item.Selected)
{
if (flag)
{
this.VerifyMultiSelect();
}
flag = true;
writer.WriteAttribute("selected", "selected");
}
writer.WriteAttribute("value", item.Value, true);
if (item.HasAttributes)
{
item.Attributes.Render(writer);
}
if (this.Page != null)
{
this.Page.ClientScript.RegisterForEventValidation(this.UniqueID, item.Value);
}
writer.Write('>');
HttpUtility.HtmlEncode(item.Text, writer);
writer.WriteEndTag("option");
writer.WriteLine();
}
}
}
}
그래서 RenderContents 메서드를 재정 의하여 내 드롭 다운 컨트롤을 만듭니다. 내 통제권이 있습니다. 잘 작동하고 있습니다. 나는 Microsoft와 똑같은 코드를 사용하고 옵션이 아닌 optgroup을 생성하기 위해 optgroup 속성을 갖는 listItem을 지원하는 약간의 조건을 추가합니다.
피드백을주세요
public class DropDownListWithOptionGroup : DropDownList
{
public const string OptionGroupTag = "optgroup";
private const string OptionTag = "option";
protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)
{
ListItemCollection items = this.Items;
int count = items.Count;
string tag;
string optgroupLabel;
if (count > 0)
{
bool flag = false;
for (int i = 0; i < count; i++)
{
tag = OptionTag;
optgroupLabel = null;
ListItem item = items[i];
if (item.Enabled)
{
if (item.Attributes != null && item.Attributes.Count > 0 && item.Attributes[OptionGroupTag] != null)
{
tag = OptionGroupTag;
optgroupLabel = item.Attributes[OptionGroupTag];
}
writer.WriteBeginTag(tag);
// NOTE(cboivin): Is optionGroup
if (!string.IsNullOrEmpty(optgroupLabel))
{
writer.WriteAttribute("label", optgroupLabel);
}
else
{
if (item.Selected)
{
if (flag)
{
this.VerifyMultiSelect();
}
flag = true;
writer.WriteAttribute("selected", "selected");
}
writer.WriteAttribute("value", item.Value, true);
if (item.Attributes != null && item.Attributes.Count > 0)
{
item.Attributes.Render(writer);
}
if (this.Page != null)
{
this.Page.ClientScript.RegisterForEventValidation(this.UniqueID, item.Value);
}
}
writer.Write('>');
HttpUtility.HtmlEncode(item.Text, writer);
writer.WriteEndTag(tag);
writer.WriteLine();
}
}
}
}
}
위의 게시물을 기반으로 작업보기 상태로이 컨트롤의 ac # 버전을 만들었습니다.
public const string OptionGroupTag = "optgroup";
private const string OptionTag = "option";
protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)
{
ListItemCollection items = this.Items;
int count = items.Count;
string tag;
string optgroupLabel;
if (count > 0)
{
bool flag = false;
for (int i = 0; i < count; i++)
{
tag = OptionTag;
optgroupLabel = null;
ListItem item = items[i];
if (item.Enabled)
{
if (item.Attributes != null && item.Attributes.Count > 0 && item.Attributes[OptionGroupTag] != null)
{
tag = OptionGroupTag;
optgroupLabel = item.Attributes[OptionGroupTag];
}
writer.WriteBeginTag(tag);
// NOTE(cboivin): Is optionGroup
if (!string.IsNullOrEmpty(optgroupLabel))
{
writer.WriteAttribute("label", optgroupLabel);
}
else
{
if (item.Selected)
{
if (flag)
{
this.VerifyMultiSelect();
}
flag = true;
writer.WriteAttribute("selected", "selected");
}
writer.WriteAttribute("value", item.Value, true);
if (item.Attributes != null && item.Attributes.Count > 0)
{
item.Attributes.Render(writer);
}
if (this.Page != null)
{
this.Page.ClientScript.RegisterForEventValidation(this.UniqueID, item.Value);
}
}
writer.Write('>');
HttpUtility.HtmlEncode(item.Text, writer);
writer.WriteEndTag(tag);
writer.WriteLine();
}
}
}
}
protected override object SaveViewState()
{
object[] state = new object[this.Items.Count + 1];
object baseState = base.SaveViewState();
state[0] = baseState;
bool itemHasAttributes = false;
for (int i = 0; i < this.Items.Count; i++)
{
if (this.Items[i].Attributes.Count > 0)
{
itemHasAttributes = true;
object[] attributes = new object[this.Items[i].Attributes.Count * 2];
int k = 0;
foreach (string key in this.Items[i].Attributes.Keys)
{
attributes[k] = key;
k++;
attributes[k] = this.Items[i].Attributes[key];
k++;
}
state[i + 1] = attributes;
}
}
if (itemHasAttributes)
return state;
return baseState;
}
protected override void LoadViewState(object savedState)
{
if (savedState == null)
return;
if (!(savedState.GetType().GetElementType() == null) &&
(savedState.GetType().GetElementType().Equals(typeof(object))))
{
object[] state = (object[])savedState;
base.LoadViewState(state[0]);
for (int i = 1; i < state.Length; i++)
{
if (state[i] != null)
{
object[] attributes = (object[])state[i];
for (int k = 0; k < attributes.Length; k += 2)
{
this.Items[i - 1].Attributes.Add
(attributes[k].ToString(), attributes[k + 1].ToString());
}
}
}
}
else
{
base.LoadViewState(savedState);
}
}
나는 이것이 어떤 사람들에게 도움이되기를 바랍니다 :-)
Irfan의 jQuery 기반 솔루션에 대한보다 일반적인 접근 방식 :
백엔드
private void _addSelectItem(DropDownList list, string title, string value, string group = null) {
ListItem item = new ListItem(title, value);
if (!String.IsNullOrEmpty(group))
{
item.Attributes["data-category"] = group;
}
list.Items.Add(item);
}
...
_addSelectItem(dropDown, "Option 1", "1");
_addSelectItem(dropDown, "Option 2", "2", "Category");
_addSelectItem(dropDown, "Option 3", "3", "Category");
...
고객
var groups = {};
$("select option[data-category]").each(function () {
groups[$.trim($(this).attr("data-category"))] = true;
});
$.each(groups, function (c) {
$("select option[data-category='"+c+"']").wrapAll('<optgroup label="' + c + '">');
});
select 및 optgroup에 대한 외부 반복기와 해당 그룹 내의 항목에 대한 내부 반복기를 사용하여이 작업을 수행했습니다.
<asp:Repeater ID="outerRepeater" runat="server">
<HeaderTemplate>
<select id="<%= outerRepeater.ClientID %>">
</HeaderTemplate>
<ItemTemplate>
<optgroup label="<%# Eval("GroupText") %>">
<asp:Repeater runat="server" DataSource='<%# Eval("Items") %>'>
<ItemTemplate>
<option value="<%# Eval("Value") %>"><%# Eval("Text") %></option>
</ItemTemplate>
</asp:Repeater>
</optgroup>
</ItemTemplate>
<FooterTemplate>
</select>
</FooterTemplate>
</asp:Repeater>
의 데이터 소스 outerRepeater
는 다음과 같은 간단한 그룹화입니다.
var data = (from o in thingsToDisplay
group oby GetAlphaGrouping(o.Name) into g
orderby g.Key
select new
{
Alpha = g.Key,
Items = g
});
그리고 알파 그룹화 문자를 얻으려면 :
private string GetAlphaGrouping(string value)
{
string firstChar = value.Substring(0, 1).ToUpper();
int unused;
if (int.TryParse(firstChar, out unused))
return "#";
return firstChar.ToUpper();
}
완벽한 솔루션은 아니지만 작동합니다. 올바른 솔루션은 더 이상 사용 웹폼에, 그러나 우리 MVC 대신합니다. :)
// How to use:
// 1. Create items in a select element or asp:DropDownList control
// 2. Set value of an option or ListItem to "_group_", those will be converted to optgroups
// 3. On page onload call createOptGroups(domElement), for example like this:
// - var lst = document.getElementById('lst');
// - createOptGroups(lst, "_group_");
// 4. You can change groupMarkerValue to anything, I used "_group_"
function createOptGroups(lst, groupMarkerValue) {
// Get an array containing the options
var childNodes = [];
for (var i = 0; i < lst.options.length; i++)
childNodes.push(lst.options[i]);
// Get the selected element so we can preserve selection
var selectedIndex = lst.selectedIndex;
var selectedChild = childNodes[selectedIndex];
var selectedValue = selectedChild.value;
// Remove all elements
while (lst.hasChildNodes())
lst.removeChild(lst.childNodes[0]);
// Go through the array of options and convert some into groups
var group = null;
for (var i = 0; i < childNodes.length; i++) {
var node = childNodes[i];
if (node.value == groupMarkerValue) {
group = document.createElement("optgroup");
group.label = node.text;
group.value = groupMarkerValue;
lst.appendChild(group);
continue;
}
// Add to group or directly under list
(group == null ? lst : group).appendChild(node);
}
// Preserve selected, no support for multi-selection here, sorry
selectedChild.selected = true;
}
Chrome 16, Firefox 9 및 IE8에서 테스트되었습니다.
위의 답변과 같이 RenderContents 메서드가 작동합니다. 또한 viewstate를 변경하는 것을 기억해야합니다. UpdatePanels에서 변경되지 않은 viewstate를 사용할 때 문제가 발생했습니다. 여기에는 Sharp Pieces Project 에서 가져온 부분이 있습니다 .
Protected Overloads Overrides Sub RenderContents(ByVal writer As HtmlTextWriter)
Dim list As DropDownList = Me
Dim currentOptionGroup As String
Dim renderedOptionGroups As New List(Of String)()
For Each item As ListItem In list.Items
If item.Attributes("OptionGroup") Is Nothing Then
RenderListItem(item, writer)
Else
currentOptionGroup = item.Attributes("OptionGroup")
If renderedOptionGroups.Contains(currentOptionGroup) Then
RenderListItem(item, writer)
Else
If renderedOptionGroups.Count > 0 Then
RenderOptionGroupEndTag(writer)
End If
RenderOptionGroupBeginTag(currentOptionGroup, writer)
renderedOptionGroups.Add(currentOptionGroup)
RenderListItem(item, writer)
End If
End If
Next
If renderedOptionGroups.Count > 0 Then
RenderOptionGroupEndTag(writer)
End If
End Sub
Private Sub RenderOptionGroupBeginTag(ByVal name As String, ByVal writer As HtmlTextWriter)
writer.WriteBeginTag("optgroup")
writer.WriteAttribute("label", name)
writer.Write(HtmlTextWriter.TagRightChar)
writer.WriteLine()
End Sub
Private Sub RenderOptionGroupEndTag(ByVal writer As HtmlTextWriter)
writer.WriteEndTag("optgroup")
writer.WriteLine()
End Sub
Private Sub RenderListItem(ByVal item As ListItem, ByVal writer As HtmlTextWriter)
writer.WriteBeginTag("option")
writer.WriteAttribute("value", item.Value, True)
If item.Selected Then
writer.WriteAttribute("selected", "selected", False)
End If
For Each key As String In item.Attributes.Keys
writer.WriteAttribute(key, item.Attributes(key))
Next
writer.Write(HtmlTextWriter.TagRightChar)
HttpUtility.HtmlEncode(item.Text, writer)
writer.WriteEndTag("option")
writer.WriteLine()
End Sub
Protected Overrides Function SaveViewState() As Object
' Create an object array with one element for the CheckBoxList's
' ViewState contents, and one element for each ListItem in skmCheckBoxList
Dim state(Me.Items.Count + 1 - 1) As Object 'stupid vb array
Dim baseState As Object = MyBase.SaveViewState()
state(0) = baseState
' Now, see if we even need to save the view state
Dim itemHasAttributes As Boolean = False
For i As Integer = 0 To Me.Items.Count - 1
If Me.Items(i).Attributes.Count > 0 Then
itemHasAttributes = True
' Create an array of the item's Attribute's keys and values
Dim attribKV(Me.Items(i).Attributes.Count * 2 - 1) As Object 'stupid vb array
Dim k As Integer = 0
For Each key As String In Me.Items(i).Attributes.Keys
attribKV(k) = key
k += 1
attribKV(k) = Me.Items(i).Attributes(key)
k += 1
Next
state(i + 1) = attribKV
End If
Next
' return either baseState or state, depending on whether or not
' any ListItems had attributes
If (itemHasAttributes) Then
Return state
Else
Return baseState
End If
End Function
Protected Overrides Sub LoadViewState(ByVal savedState As Object)
If savedState Is Nothing Then Return
' see if savedState is an object or object array
If Not savedState.GetType.GetElementType() Is Nothing AndAlso savedState.GetType.GetElementType().Equals(GetType(Object)) Then
' we have just the base state
MyBase.LoadViewState(savedState(0))
'we have an array of items with attributes
Dim state() As Object = savedState
MyBase.LoadViewState(state(0)) '/ load the base state
For i As Integer = 1 To state.Length - 1
If Not state(i) Is Nothing Then
' Load back in the attributes
Dim attribKV() As Object = state(i)
For k As Integer = 0 To attribKV.Length - 1 Step +2
Me.Items(i - 1).Attributes.Add(attribKV(k).ToString(), attribKV(k + 1).ToString())
Next
End If
Next
Else
'load it normal
MyBase.LoadViewState(savedState)
End If
End Sub
참고 URL : https://stackoverflow.com/questions/130020/dropdownlist-control-with-optgroups-for-asp-net-webforms
'developer tip' 카테고리의 다른 글
Visual Studio에서 푸시되지 않은 나가는 커밋을 제거하는 방법은 무엇입니까? (0) | 2020.11.17 |
---|---|
Capistrano에서 Git 하위 디렉터리 배포 (0) | 2020.11.17 |
n 개의 마지막 행에서 mysql 선택 (0) | 2020.11.17 |
Clojure XML 구문 분석 (0) | 2020.11.17 |
Thymeleaf : Concatenation-식으로 구문 분석 할 수 없습니다. (0) | 2020.11.16 |