簡體   English   中英

渲染嵌套服務器控件

[英]Rendering Nested Server Controls

這應該相對容易。 我不知道為什么要為此苦苦掙扎,但是Google無法幫助我找到我想做的事的例子。

我正在構建帶有LI的UL的簡單嵌套結構的導航/菜單。 放置在頁面上的父對象稱為NavController。 它具有NavItems的集合。

因此,我幾乎讓NavController處理了構建基本UI,創建CSS和JavaScript的過程。 它還為最高級別的LI創建了基本UL。 根據我的研究和了解,UI的創建應在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方法實際上是構建頂級LI。 我不確定如何調用此方法,但我可以看到它的名稱。 在BuildList函數中,我將NavItem對象添加到innerContents的Controls集合中。

首先,這是正確的嗎? 將另一個自定義服務器控件放置在UL內部(需要注意的是,自定義控件基本上是呈現LI;稍后將對此進行詳細說明)?

永遠不會為NavItem調用CreateChildControls。 在Internet上四處逛逛之后,似乎是因為我從未打電話給確保兒童控件。 這使我感到困惑,因為它只會在ChildControlsCreated屬性為false時才會觸發。 一旦運行,此屬性將變為true。 如果我在NavItem上設置了Text和Href並在設置了其中一個時調用了sureChildControls,那么如何將另一個的值放入任何子控件中?

只是為了阻塞一些屏幕空間,這是我到目前為止為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;
    }
  }
}

我不明白為什么我不能只在其公共屬性中設置值和文本,然后在渲染之前使用某種方法或方式將其放入控件中。

拜托,請給我指出正確的方法。 我需要一堆這樣的小控件,基本上可以采用相同的方法。 我將很快啟動一個基本的工具欄,該信息將有所幫助!

編輯-放置代碼以顯示清單建築物以供澄清:

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

重寫CreateChildControls()之后,您基本上將負責確保正確創建嵌套控件。

您的方法似乎很標准,但是,對於您的簡單屬性,我認為您不需要調用SecureChildControls()。 如果您是從該函數的MSDN文檔中挑選的,請再看一看-他們提供的“ Text”屬性示例正在從其子控件之一中檢索文本值,這意味着屬性訪問器需要確保該子控件存在控件。

您無法保證何時有人可以訪問您的控件,這就是為什么您要在對Controls集合中的控件進行任何訪問之前先放入SecureChildControl()調用的原因。 在正常的頁面生命周期中,當ASP.net將您的復合控件添加到頁面時,將調用CreateChildControls()。 如果沒有人觸摸您的控件並且沒有進行數據綁定或任何操作,則在第一頁上的PreRender加載之前,可能不會發生這種情況。

在后續的回發中,將在ViewState處理期間調用CreateChildControls,否則任何代碼都可能觸發復合控件以開始創建其子控件。 例如,FindControl()將自動執行此操作-這可能發生在OnInit()中。

希望能有所幫助。 我認為您在正確的軌道上。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM