Тег <optgroup> представляет собой контейнер, внутри которого располагаются теги <option> объединенные в одну группу. Особенностью тега <optgroup> является то, что он не выделяется как обычный элемент списка, акцентируется с помощью жирного начертания, а все элементы, входящие в этот контейнер, смещаются вправо от своего исходного положения.
Хороший тег, но недавно я столкнулся с неожиданным открытием. Оказывается элемент управления DropDownList не поддерживает тег optgroup, хотя он и является HTML стандартом. Простое подсовывание других элементов управления или ручное вписывание результата не дает. Что же делать? Паниковать не стоит, решение есть.
Необходимо создать новый класс, унаследованный от DropDownList. В нем добавим метод добавления optgroup, и переопределим метод отрисовки содержимого. Ниже привожу готовый класс.
public class DropDownListX : DropDownList
{
public void AddItemGroup(string groupTitle)
{
this.Items.Add(new ListItem(groupTitle, "$$OPTGROUP$$OPTGROUP$$"));
}
protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)
{
if (this.Items.Count > 0)
{
bool selected = false;
bool optGroupStarted = false;
for (int i = 0; i < this.Items.Count; i++)
{
ListItem item = this.Items[i];
if (item.Enabled)
{
if (item.Value == "$$OPTGROUP$$OPTGROUP$$")
{
if (optGroupStarted)
writer.WriteEndTag("optgroup");
writer.WriteBeginTag("optgroup");
writer.WriteAttribute("label", item.Text);
writer.Write('>');
writer.WriteLine();
optGroupStarted = true;
}
else
{
writer.WriteBeginTag("option");
if (item.Selected)
{
if (selected)
{
this.VerifyMultiSelect();
}
selected = true;
writer.WriteAttribute("selected", "selected");
}
writer.WriteAttribute("value", item.Value, true);
if (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("option");
writer.WriteLine();
}
}
}
if (optGroupStarted)
{
writer.WriteEndTag("optgroup");
}
}
}
}
Идея состоит в том, что используя метод AddItemGroup мы добавляем в коллекцию списка запись с определенным значением value, в данном случае "$$OPTGROUP$$OPTGROUP$$". Затем, вручную отрисовываем все содержимое в нашем переопределенном методе. Встречая приведенное выше значение, мы отрисовываем его как тег optgroup, в противном случае как обычный option.
На первый взгляд может показаться ужасно, но это простое и ясное решение.