Как создать пользовательский/серверный элемент управления ASP.NET, который использует список asp:ListItem в качестве дочерних элементов управления?

Я хочу создать элемент управления пользователя/сервера, который будет создан примерно так:

<my:MyListControl runat="server">
   <asp:ListItem Text="Test1" Value="Test1" />
   <asp:ListItem Text="Test2" Value="Test2" />
</my:MyListControl>

Я просто ищу здесь начало: статьи или примеры кода.

От какого базового класса я должен наследовать? Что переопределить?

Возможно, как настроить, какие подэлементы принимает мой элемент управления (my:ListItem вместо asp:ListItem).

Что я хочу сделать, так это создать очень простой элемент управления хлебными крошками для небольшого раздела моего сайта. У меня все это работает со стандартными элементами управления ASP.NET, но элементы добавляются в код, что означает, что исправление орфографической ошибки или ошибки форматирования требует перекомпиляции, что не идеально.

РЕДАКТИРОВАТЬ:

Вот мой код с добавлением предложения Джоша ниже:

Пространство имен MySite.Controls Разделяемый класс BreadCrumbs наследует UserControl

    Private m_BreadCrumbs As New List(Of BreadCrumbItem)

    <PersistenceMode(PersistenceMode.InnerProperty)> _
    Public Property Items() As List(Of BreadCrumbItem)
        Get
            Return m_BreadCrumbs
        End Get
        Set(ByVal value As List(Of BreadCrumbItem))
            m_BreadCrumbs = value
        End Set
    End Property

    Private Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
        Bind()
    End Sub

    Private Sub Bind()
        lvCrumbs.DataSource = Items
        Me.DataBind()
    End Sub
End Class

Public Class BreadCrumbItem
    Private m_Text As String
    Public Property Text() As String
        Get
            Return m_Text
        End Get
        Set(ByVal value As String)
            m_Text = value
        End Set
    End Property

    Private m_Url As String
    Public Property Url() As String
        Get
            Return m_Url
        End Get
        Set(ByVal value As String)
            m_Url = value
        End Set
    End Property
End Class

Конец пространства имен

Тогда код моей страницы выглядит так:

<%@ Page Language="VB" AutoEventWireup="false" Inherits="MySite.MyPage" Title="My Page" Codebehind="MyPage.aspx.vb" %>
<%@ Register TagPrefix="my" Namespace="MySite.Controls" Assembly="MySite" %>
<my:BreadCrumbs ID="breadcrumbs" runat="server">
    <Items>
        <my:BreadCrumbItem Text="Another page" Url="AnotherPage.aspx" />
    </Items>
</my:BreadCrumbs>

person slolife    schedule 27.04.2009    source источник
comment
Какова конечная цель HTML-разметки? Что-то вроде: ‹ul› ‹li›Test1‹/li› ‹li›Test2‹/li› ‹/ul› Зачем использовать ListItem, а не какой-то другой тип?   -  person ahsteele    schedule 27.04.2009
comment
Да, HTML, который я выплевываю, — это ul/li. Нет необходимости в asp:ListItem, просто не знал, как еще это назвать, когда задал вопрос   -  person slolife    schedule 28.04.2009


Ответы (2)


Вы можете добавить свойство в код пользовательского элемента управления, например:

[PersistenceMode(PersistenceMode.InnerProperty)]
public List<ListItem> Items
{
    get;
    set;
}

Тогда ваша разметка будет:

<my:MyListControl runat="server">
  <Items>
    <asp:ListItem/>
  </Items>
</my:myListControl>

Чтобы сделать так, чтобы ListItem мог быть вашим собственным элементом списка (что я рекомендую делать, а не использовать asp.net). Вам нужно создать свой собственный класс.

Вот пример серверного элемента управления, который я использую (я удалил много шума, так что это всего лишь скелет):

   [ToolboxData("<{0}:Menubar runat=server></{0}:Menubar>")]
    [System.ComponentModel.DesignTimeVisible(false)]
    public class Menubar : WebControl, IPostBackEventHandler
    {

        private List<MenuItem> _menuItems = new List<MenuItem>();
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public List<MenuItem> MenuItems
        {
            get
            {
                return _menuItems;
            }
        }

    }
    [ToolboxItem(false)]
    [ParseChildren(true, "MenuItems")]
    public class MenuItem
    {
        private string _clientClick;
        private List<MenuItem> _menuItems = new List<MenuItem>();

        [Localizable(true)]
        public string Title { get; set; }
        public string Href { get; set; }
        public string Id { get; set; }
        [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
        public List<MenuItem> MenuItems
        {
            get { return _menuItems; }
            set { _menuItems = value; }
        }
    }

Теперь я могу использовать это как:

<my:Menubar runat="server" ID="menuBar">
    <MenuItems>
        <my:MenuItem Title="Save" Href="javascript:saveItem(this);"  />
        <my:MenuItem Title="Print" Href="javascript:void(0);">
            <MenuItems>
                <my:MenuItem Title="Preview" Href=""/>
                <my:MenuItem Title="To Pdf" Href="javascript:"/>
            </MenuItems>
        </my:MenuItem>
    </MenuItems>
</my:Menubar>
person JoshBerke    schedule 27.04.2009
comment
Кажется, это то, что мне нужно. Единственное, что я сейчас зависаю, это почему мой @Register TagPrefix=my Namespace=MySite.Controls не работает для получения пользовательского класса элемента списка? Есть идеи? Он получает родительский элемент управления (Menubar в вашем примере), но я не могу сделать my:MyListItem внутри тега Items. - person slolife; 27.04.2009
comment
Не бери в голову. Необходимо добавить параметр Assembly в директиву @Register. Теперь это работает. Спасибо Джош - person slolife; 28.04.2009

Используйте asp:Repeater, затем привяжите его к списку объектов, которые вы хотите добавить в свою навигационную крошку. Вы можете использовать шаблон для настройки самих элементов и разделителей.

person Alan Jackson    schedule 27.04.2009
comment
Я хотел что-то более четкое, чем управление повторителем. - person slolife; 28.04.2009