Asp.net webforms ListBox Группировка
У меня есть страница веб-формы, на которой есть список со списком камер. Он заполняется таблицей данных, в которой есть столбец для имени камеры, IP-адреса и группы.
DataClasses1DataContext dc = new DataClasses1DataContext();
public List<CameraTable> CameraListBox;
public List<ListItem> SelectedListBox;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
CameraListBox = (from x in dc.CameraTables
select x).ToList();
ListBox1.DataSource = CameraListBox;
ListBox1.DataTextField = "CameraName";
ListBox1.DataValueField = "IPAddress";
ListBox1.DataBind();
}
}
Этот код прекрасно работает для заполнения списка с именами камер, но я хотел бы сделать так, чтобы в нем была группа, а затем камеры в этой группе. Я понятия не имею, как это сделать. Я научился не задавать вопросы здесь, если только мне это не нужно, но я исследовал это в течение нескольких дней и не могу ничего найти. Это возможно? Должен ли я сделать все это программно?
1 ответ
Основано на великолепном подходе ответа SO: Как добавить группы опций в раскрывающийся список ASP.NET?
ListBox в ASP.NET не поддерживает optgroup
html требуется для группировки, которую вы запрашиваете. Один из подходов к внедрению этой функциональности - добавление атрибута в элементы списка для захвата категории, а затем использование вашей любимой интерфейсной среды для изменения DOM для создания соответствующей optgroup
состав.
Поскольку элемент управления ListBox не имеет OnItemDataBound
тип события, вы не можете получить доступ к каждому элементу в процессе привязки данных. Так как это будет единственный раз, когда вы можете получить доступ к group
из записи CameraTable вы не можете выполнить привязку данных - вы должны составить список самостоятельно, чтобы добавить группу в качестве атрибута html к каждой опции.
Приведенный ниже метод помогает создать один элемент списка с атрибутом данных, если это возможно.
public ListItem GetListItem(CameraTable item)
{
var listItem = new ListItem(item.CameraName, item.IPAddress);
if (string.IsNullOrEmpty(item.GroupName) == false)
listItem.Attributes.Add("data-category", item.GroupName);
return listItem;
}
Затем, вместо вашего кода привязки данных в списке, просто создайте список напрямую. Вы должны будете учитывать состояние представления и постоянство в обратных передачах, но по крайней мере это подход:
var itemsToAdd = CameraListBox
.Select(c => GetListItem(c))
.ToArray();
ListBox1.Items.AddRange(itemsToAdd);
Наконец, вытащите ваш любимый клиентский фреймворк (ниже JQuery) для создания элементов optgroup.
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 + '">');
});
Это должно завершить группировку для ваших элементов.
ОБНОВЛЕНИЕ НА ОСНОВЕ КОММЕНТАРИЙНОГО ВОПРОСА
Если вы собираетесь поместить его в заголовок HTML, вы должны убедиться, что DOM загружен - иначе вы манипулируете элементами, которые еще не готовы.
Чтобы остаться с JQuery здесь, оберните клиентский скрипт в $(document).ready
событие. Я включил полный образец страницы ниже.
ASPX Page
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="Web.WebForm1" %>
<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
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 + '">');
});
});
</script>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="BodyContent" runat="server">
<asp:ListBox ID="ListBox1" runat="server" Height="100" Width="200" />
</asp:Content>
ASPX Code Behind (с проверенным контекстом данных и камерой)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI.WebControls;
namespace Web
{
public partial class WebForm1 : System.Web.UI.Page
{
DataClasses1DataContext dc = new DataClasses1DataContext();
public List<CameraTable> CameraListBox;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
CameraListBox = (from x in dc.CameraTables
select x).ToList();
var itemsToAdd = CameraListBox
.Select(c => GetListItem(c))
.ToArray();
ListBox1.Items.AddRange(itemsToAdd);
}
}
public ListItem GetListItem(CameraTable item)
{
var listItem = new ListItem(item.CameraName, item.IPAddress);
if (string.IsNullOrEmpty(item.GroupName) == false)
listItem.Attributes.Add("data-category", item.GroupName);
return listItem;
}
}
public class DataClasses1DataContext
{
public IQueryable<CameraTable> CameraTables
{
get
{
return new List<CameraTable>()
{
new CameraTable("Back Hallway", "1.1.1.1", "Floor 1"),
new CameraTable("Bedroom 1", "2.2.2.2", "Floor 1"),
new CameraTable("Bedroom 2", "3.3.3.3", "Floor 2"),
}.AsQueryable();
}
}
}
public class CameraTable
{
public string CameraName { get; set; }
public string IPAddress { get; set; }
public string GroupName { get; set; }
public CameraTable(string name, string ip, string group)
{
this.CameraName = name;
this.IPAddress = ip;
this.GroupName = group;
}
}
}