2009-03-26 15 views
0

Dies sollte relativ einfach sein. Ich weiß nicht, warum ich damit kämpfe, aber Google kann mir nicht helfen, ein Beispiel dafür zu finden, was ich tun möchte.Rendern von geschachtelten Serversteuerelementen

Ich baue eine Navigation/Menü aus einer einfachen verschachtelten Struktur von ULs mit LIs. Das übergeordnete Objekt, das auf der Seite platziert wird, heißt NavController. Es enthält eine Sammlung von NavItems.

Also ließ ich den NavController ziemlich viel damit anfangen, die Basis-UI zu erstellen, CSS und JavaScript zu erstellen. Es erstellt auch die Basis-UL für die oberste Ebene von LIs. Aus meiner Forschung und Verständnis sollte die UI-Erstellung in der CreateChildControls-Methode erfolgen.

Hier ist mein Code:

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(); 
} 

Die Buildlist Methode baut eigentlich die Top-Level-LIs. Ich bin mir nicht sicher, wie diese Methode heißt, aber ich kann sehen, dass es so ist. In der BuildList-Funktion füge ich die NavItem-Objekte zur Controls-Auflistung von innerContents hinzu.

Zunächst einmal, ist das korrekt? Platzieren eines anderen benutzerdefinierten Serversteuerelements innerhalb eines UL (mit der Einschränkung, dass das benutzerdefinierte Steuerelement im Grunde eine LI rendert; mehr dazu später)?

Die CreateChildControls wird niemals für das NavItem aufgerufen. Nachdem ich mich im Internet umgesehen habe, schien es so, als ob ich EnsureChildControls nie aufgerufen hätte. Das verwirrt mich, da es nur ausgelöst wird, wenn die ChildControlsCreated-Eigenschaft falsch ist. Sobald es ausgeführt wird, wird diese Eigenschaft wahr. Wenn ich einen Text und eine Href auf dem NavItem habe und EnsureChildControls aufgerufen wird, wenn einer von beiden gesetzt ist, wie wird dann der Wert des anderen in ein Untersteuerelement eingefügt?

Gerade hier etwas Platz auf dem Bildschirm zu verstopfen ist der Code, den ich bisher für die NavItem haben:

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; 
    } 
    } 
} 

Ich verstehe nicht, warum ich nicht nur den Wert und Text in ihren öffentlichen einstellen Eigenschaften und verwenden Sie dann eine Methode oder eine Methode, um es vor dem Rendern in die Steuerelemente zu platzieren.

Bitte, bitte einige mich auf die richtige Weise, dies zu tun. Ich habe eine Menge dieser kleinen Kontrollen, die ich machen muss, die im Grunde denselben Ansatz machen. Ich werde bald eine rudimentäre Toolbar starten und diese Information würde helfen!

EDIT - Platzierung in Code, der die Liste Gebäude zur Verdeutlichung zeigt:

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

Antwort

2

Sobald Sie Createchildcontrols() außer Kraft setzen, Sie im Grunde verantwortlich werden, sicherzustellen, dass Ihre verschachtelten Kontrollen ordnungsgemäß erstellt bekommen.

Ihr Ansatz scheint ziemlich Standard, aber für Ihre einfachen Eigenschaften, ich glaube nicht, dass Sie EnsureChildControls() aufrufen müssen. Wenn Sie dies aus den MSDN-Dokumenten der Funktion entnommen haben, sehen Sie sich das anders an - das Beispiel der Eigenschaft "Text", das sie angeben, ruft den Textwert von einem seiner untergeordneten Steuerelemente ab, was bedeutet, dass der Eigenschaftenaccessor das untergeordnete Element sicherstellen muss Kontrollen existieren.

Sie können nicht garantieren, dass jemand auf Ihr Steuerelement zugreifen könnte. Aus diesem Grund würden Sie Aufrufe von EnsureChildControl() vor jedem Zugriff auf ein Steuerelement in der Controls-Auflistung einfügen. In einem normalen Seitenlebenszyklus wird CreateChildControls() aufgerufen, wenn ASP.net Ihr zusammengesetztes Steuerelement der Seite hinzufügt.Dies kann erst geschehen, wenn PreRender auf der ersten Seite geladen wird, wenn niemand deine Kontrolle berührt und es keine Daten oder irgendetwas anderes gibt.

Bei nachfolgenden Postbacks wird CreateChildControls während der ViewState-Verarbeitung aufgerufen, oder jeder Code berührt möglicherweise ein zusammengesetztes Steuerelement, um die untergeordneten Steuerelemente zu erstellen. FindControl() wird dies zum Beispiel automatisch tun - und dies könnte in OnInit() passieren.

Hoffe, dass hilft. Ich denke du bist auf dem richtigen Weg.

+0

Mit Blick auf den Listencode, den ich hinzugefügt habe, können Sie erklären, warum, wenn ich das NavItem zum UL hinzufüge, es nie wieder rendert. Durch Render, ich meine ich weiß nicht, wo ich den Code platzieren sollte, der seine untergeordneten Steuerelemente erstellt. Ich würde denken, es wäre die gleiche Methode. –

Verwandte Themen