2009-03-26 3 views
0

Это должно быть относительно легко. Я не знаю, почему я борюсь с этим, но Google не может помочь мне найти пример того, что я хочу делать.Рендеринг вложенных серверных элементов управления

Я создаю навигацию/меню из простой вложенной структуры UL с LI. Родительский объект, который помещается на страницу, называется NavController. В нем есть коллекция NavItems.

Так что я в значительной степени позволяю NavController обрабатывать базовый интерфейс, создавая CSS и JavaScript. Он также создает базовый UL для верхнего уровня LI. Из моих исследований и понимания создание пользовательского интерфейса должно выполняться в методе CreateChildControls.

Вот мой код:

protected override void CreateChildControls() 
{ 
    Controls.Clear(); 

    this.Page.RegisterClientJavaScript("~/Resources/Script/SideNav.js"); 
    _ClientObject = this.GetClientJavaScriptObject("SideNav", this.ClientID); 

    Controls.Add(_BaseContainer); 

    HtmlGenericControl innerContents = this.BuildBaseContainer(); 
    this.BuildList(innerContents); 

    _ClientObject.AddParameter("BaseContainerID", _BaseContainer.ClientID, true); 
    _ClientObject.AddParameter("ImgId", _SideBarTabImg.ClientID, true); 
    _ClientObject.AddParameter("SideBarContentsId", _SideBarContents.ClientID, true); 

    base.CreateChildControls(); 
} 

Метод BuildList фактически строит верхние Lis уровня. Я не уверен, как называется этот метод, но я вижу, что это так. Внутри функции BuildList я добавляю в коллекцию ControlContents элементы NavItem.

Прежде всего, это правильно? Размещение другого настраиваемого управления сервером внутри UL (с оговоркой, что пользовательский элемент управления в основном выполняет LI, более подробно об этом позже)?

CreateChildControls никогда не вызывается для NavItem. Оглянувшись в Интернете, казалось, что это было потому, что я никогда не звонил в EnsureChildControls. Это меня смущает, потому что оно будет срабатывать только тогда, когда свойство ChildControlsCreated является ложным. После запуска это свойство становится истинным. Если у меня есть текст и Href в NavItem, и EnsureChildControls вызывается, когда каждый из них задан, то каким образом значение другого будет помещено в любой субконтроллер?

Просто засоряют некоторое пространство экрана здесь это код, который я до сих пор для NavItem:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Text; 
using System.Web; 
using System.Web.UI; 
using System.Web.UI.WebControls; 
using System.Web.UI.HtmlControls; 

namespace AthletesCafe.Web.WebControls.SideNav 
{ 
    [ToolboxData("<{0}:NavItem runat=server></{0}:NavItem>")] 
    public class NavItem : ExtendedWebControl 
    { 
    private string _Text; 
    private string _Value; 
    private IList<NavItem> _ChildItems = new List<NavItem>(); 

private HtmlGenericControl _ListItem = new HtmlGenericControl("LI"); 
private HtmlAnchor _Link = new HtmlAnchor(); 
private HtmlGenericControl _SubList = new HtmlGenericControl("UL"); 

public string Text 
{ 
    get 
    { 
    EnsureChildControls(); 
    return _Text; 
    } 

    set 
    { 
    EnsureChildControls(); 
    _Text = value; 
    _Link.InnerText = _Text; 
    } 
} 

public string Value 
{ 
    get 
    { 
    EnsureChildControls(); 
    return _Value; 
    } 

    set 
    { 
    EnsureChildControls(); 
    _Value = value; 
    _Link.HRef = _Value; 
    } 
} 

protected override void CreateChildControls() 
{ 
    Controls.Clear(); 
    Controls.Add(_ListItem); 

    _ListItem.Controls.Add(_Link); 

    base.CreateChildControls(); 
} 

public NavItem AddChildItem(string text, string url) 
{ 
    EnsureChildControls(); 

    NavItem newItem = new NavItem(); 
    newItem.Text = text; 
    newItem.Value = url; 

    _ChildItems.Add(newItem); 
    this.BuildSubList(); 
    return newItem; 
} 

private void BuildSubList() 
{ 
    _SubList.Controls.Clear(); 

    if (_ChildItems.Count > 0) 
    { 
    if (!_ListItem.Controls.Contains(_SubList)) 
     _ListItem.Controls.Add(_SubList); 

    foreach (NavItem item in _ChildItems) 
     _SubList.Controls.Add(item); 
    } 
} 

protected override void Render(HtmlTextWriter writer) 
{ 
    RenderContents(writer); 
} 

protected override void RenderContents(HtmlTextWriter writer) 
{ 
    _ListItem.RenderControl(writer); 
    //base.RenderContents(writer); 
} 

    public override string ToString() 
    { 
     EnsureChildControls(); 
     return _Text + " - " + _Value; 
    } 
    } 
} 

Я не понимаю, почему я не могу просто установить значение и текст в их общественности свойства, а затем использовать какой-либо метод или способ, чтобы поместить его в элементы управления перед рендерингом.

Пожалуйста, пожалуйста, сообщите мне, как правильно это сделать. У меня есть куча этих небольших элементов управления, которые мне нужно сделать, чтобы в принципе сделать такой же подход. Я скоро начну рудиментарную панель инструментов, и эта информация поможет!

EDIT - размещение в коде, который показывает здание списка для уточнения:

HtmlGenericControl list = new HtmlGenericControl("UL"); 
innerContents.Controls.Add(list); 
foreach (NavItem item in _Items) 
{ 
    list.Controls.Add(item); 
} 

ответ

2

После того, как переопределить CreateChildControls(), вы в основном на себя ответственность за то, чтобы ваши вложенные элементы управления получить созданы надлежащим образом.

Ваш подход кажется довольно стандартным, однако, для ваших простых свойств, я не думаю, что вам нужно позвонить EnsureChildControls(). Если вы выбрали это из документов MSDN в функции, посмотрите еще раз - пример свойства «Текст», который они дают, - это получение значения текста из одного из его дочерних элементов управления, что означает, что аксессуар свойства должен убедиться, что дочерний элемент существует контроль.

Вы не можете гарантировать, что кто-то может получить доступ к вашему элементу управления, поэтому вы должны поместить вызовы EnsureChildControl() перед любым доступом к элементу управления в своей коллекции Controls. В обычном жизненном цикле страницы CreateChildControls() будет вызван, когда ASP.net начнет добавлять ваш составной элемент управления на страницу.Это может не произойти до тех пор, пока PreRender не загрузит первую страницу, если никто не прикасается к вашему управлению, и он не привязывается к данным или чему-либо еще.

При последующих обратных передачах CreateChildControls будет вызываться во время обработки ViewState, или любой код может касаться составного элемента управления, чтобы начать создавать дочерние элементы управления. FindControl() будет делать это автоматически, например - и это может произойти в OnInit().

Надеюсь, что это поможет. Я думаю, ты на правильном пути.

+0

Глядя на код списка, который я добавил, вы можете объяснить, почему, когда я добавляю NavItem к UL, который он никогда не выводит. Посредством рендеринга я имею в виду, что я не знаю, где в нем я должен поместить код, который создает его дочерние элементы управления. Я бы подумал, что это будет тот же метод. –

Смежные вопросы