2009-04-08 10 views
8

Ich habe eine Masterseite, die 2 Ebenen verschachtelt ist. Es hat eine Masterseite und diese Masterseite hat eine Masterseite.Suchen von Steuerelementen in verschachtelten Masterseiten

Wenn ich Steuerelemente in einem Content mit dem Namen „bcr“ stick - ich die Bedienelemente wie so finden müssen:

Label lblName =(Label)Master.Master.FindControl("bcr").FindControl("bcr").FindControl("Conditional1").FindControl("ctl03").FindControl("lblName"); 

Bin ich total verloren? Oder muss es so gemacht werden?

Ich bin im Begriff, mit einem MultiView zu arbeiten, das innerhalb einer bedingten Inhaltskontrolle ist. Wenn ich also die Ansicht ändern möchte, muss ich einen Hinweis auf dieses Kontrollrecht bekommen? Diese Referenz zu bekommen, wird noch schlimmer! Gibt es einen besseren Weg? Zum einen

Dank

Antwort

4

, sollten Sie wissen, dass Masterpages innerhalb Seiten tatsächlich sitzen. So sehr, dass das Load-Ereignis einer MasterPage tatsächlich nach dem Load-Ereignis Ihres ASPX aufgerufen wird.

Dies bedeutet, dass das Page-Objekt tatsächlich das höchste Steuerelement in der Steuerungshierarchie ist. Wenn Sie dies wissen, besteht der beste Weg, ein Steuerelement in einer solchen verschachtelten Umgebung zu finden, darin, eine rekursive Funktion zu schreiben, die alle Steuerelemente und untergeordneten Steuerelemente durchläuft, bis die gesuchte gefunden wird. In diesem Fall sind Ihre MasterPages tatsächlich untergeordnete Steuerelemente des Hauptsteuerelements.

Sie gelangen auf das Haupt-Page-Objekt aus dem Inneren jeder Kontrolle wie folgt aus:

C#:

this.Page;

VB.NET

Me.Page

ich, dass in der Regel finden, ist die Kontrolle der Klasse Findcontrol() -Methode ziemlich nutzlos ist, da die Umgebung immer verschachtelt.

Weil, wenn dies, ich habe beschlossen, .NET 3.5 neue Erweiterungsfunktionen zu verwenden, um die Control-Klasse zu erweitern.

Durch den nachfolgenden Code (VB.NET) verwendet wird, in etwa Ihren AppCode Ordner, alle Ihre Kontrollen werden nun eine rekursive Fund peform von FindByControlID Aufruf()

Public Module ControlExtensions 
    <System.Runtime.CompilerServices.Extension()> _ 
    Public Function FindControlByID(ByRef SourceControl As Control, ByRef ControlID As String) As Control 
     If Not String.IsNullOrEmpty(ControlID) Then 
      Return FindControlHelper(Of Control)(SourceControl.Controls, ControlID) 
     Else 
      Return Nothing 
     End If 
    End Function 

    Private Function FindControlHelper(Of GenericControlType)(ByVal ConCol As ControlCollection, ByRef ControlID As String) As Control 
     Dim RetControl As Control 

     For Each Con As Control In ConCol 
      If ControlID IsNot Nothing Then 
       If Con.ID = ControlID Then 
        Return Con 
       End If 
      Else 
       If TypeOf Con Is GenericControlType Then 
        Return Con 
       End If 
      End If 

      If Con.HasControls Then 
       If ControlID IsNot Nothing Then 
        RetControl = FindControlByID(Con, ControlID) 
       Else 
        RetControl = FindControlByType(Of GenericControlType)(Con) 
       End If 

       If RetControl IsNot Nothing Then 
        Return RetControl 
       End If 
      End If 
     Next 

     Return Nothing 
    End Function 

End Module 
22

Finding Kontrollen ist ein Schmerz, und ich habe diese Methode wurde verwendet, die ich aus dem CodingHorror blog eine ganze Weile bekam vor, mit einer einzigen Änderung, die null zurückgibt, wenn eine leere ID übergeben wird.

/// <summary> 
/// Recursive FindControl method, to search a control and all child 
/// controls for a control with the specified ID. 
/// </summary> 
/// <returns>Control if found or null</returns> 
public static Control FindControlRecursive(Control root, string id) 
{ 
    if (id == string.Empty) 
     return null; 

    if (root.ID == id) 
     return root; 

    foreach (Control c in root.Controls) 
    { 
     Control t = FindControlRecursive(c, id); 
     if (t != null) 
     { 
      return t; 
     } 
    } 
    return null; 
} 

in Ihrem Fall, ich glaube, Sie bräuchten Folgendes:

Die Verwendung dieser Methode ist im Allgemeinen viel bequemer, da Sie nicht genau wissen müssen, wo sich das Steuerelement befindet (vorausgesetzt, Sie kennen die ID natürlich), wenn Sie jedoch Steuerelemente mit der Der gleiche Name, Sie werden wahrscheinlich ein seltsames Verhalten bekommen, das könnte etwas sein, auf das Sie achten sollten.

+0

Das funktioniert perfekt. Vielen Dank. –

+0

+1 danke das hat mir auch geholfen – leen3o

+0

+1 Ich weiß, das ist wie 5 Jahre alt, aber diese Methode hat mir Kopfschmerzen erspart, danke! – psoshmo

4

Obwohl ich die Rekursion liebe und mit andy und Mun übereinstimme, ist ein anderer Ansatz, den Sie vielleicht in Betracht ziehen, ein strongly typed Master page zu haben. Alles, was Sie tun müssen, ist eine Direktive in Ihrer Aspx-Seite hinzuzufügen.

stattdessen eine Seite der Kontrolle von Ihrer Master-Seite für den Zugriff, betrachten von der Seite selbst eine Kontrolle in der Masterseite zugreifen. Dieser Ansatz ist sehr sinnvoll, wenn Sie auf Ihrer Masterseite eine Kopfzeilenbezeichnung haben und den Wert für jede Seite festlegen möchten, die den Master verwendet.

Ich bin nicht 100% sicher, aber ich denke, das wäre eine einfachere Technik mit verschachtelten Masterseiten, da Sie den VirtualPath einfach auf den Master richten, der das Steuerelement enthält, auf das Sie zugreifen möchten. Es könnte sich jedoch als schwierig erweisen, wenn Sie auf zwei Steuerelemente zugreifen möchten, eines auf jeder entsprechenden Masterseite.

+0

Ja, guter Punkt. Manchmal ist es gut, diese Funktionalität in eine Art Methode oder Eigenschaft in Ihrer benutzerdefinierten Seitenbasis einzufügen. Obwohl es natürlich nicht schadet, eingebaute rekursive Kontroller zu haben – andy

1

Ich habe die <%@ MasterType VirtualPath="~/MyMaster.master" %> Methode verwendet. Ich habe eine Eigenschaft in der Hauptvorlage und dann in der Detailmasterseite andere Eigenschaft mit dem gleichen Namen, der Haupthaupteigenschaft aufruft und es funktioniert gut.

Ich habe dies in der Hauptmasterseite

public string MensajeErrorString 
    { 
     set 
     { 
      if (value != string.Empty) 
      { 
       MensajeError.Visible = true; 
       MensajeError.InnerHtml = value; 
      } 
      else 
       MensajeError.Visible = false; 
     } 


    } 

dies ist nur ein div-Element, das eine Fehlermeldung zeigen. Ich möchte diese Eigenschaft in den Seiten mit der Detailmasterseite verwenden (diese ist mit dem Hauptmaster verschachtelt).

Dann im Detail Master Ich habe diese

public string MensajeErrorString 
    { 
     set 
     { 
       Master.MensajeErrorString = value; 
     } 

    } 

Im Haupt Master-Eigenschaft aus dem Detail Master Aufruf das gleiche Verhalten zu erstellen.

0

Ich habe es gerade perfekt funktioniert.

In contentpage.aspx schrieb ich folgendes:

If Master.Master.connectsession.IsConnected Then my coded comes in here End If

2

Hier ist ein Code, mehr generisch ist und arbeitet mit einem kundenspezifischen Zustand (dh ein Lambda-Ausdruck sein kann!)

Aufruf:

Control founded = parent.FindControl(c => c.ID == "youdId", true); 

Steuerungserweiterung

public static class ControlExtensions 
{ 
    public static Control FindControl(this Control parent, Func<Control, bool> condition, bool recurse) 
    { 
     Control founded = null; 
     Func<Control, bool> search = null; 
     search = c => c != parent && condition(c) ? (founded = c) != null : 
                recurse ? c.Controls.FirstOrDefault(search) != null : 
                (founded = c.Controls.FirstOrDefault(condition)) != null; 
     search(parent); 
     return founded; 
    } 
} 
Verwandte Themen