2010-01-05 6 views
4

La propriété Get de la propriété Visible d'un contrôle recherche récursivement l'arborescence pour indiquer si le contrôle sera rendu ou non.Comment obtenir l'ensemble/la valeur réelle de la propriété Visible dans Asp.Net

J'ai besoin d'un moyen de voir quelle est la valeur visible "locale" d'un contrôle indépendamment de ce que ses contrôles parents sont définis. c'est-à-dire si elle était elle-même définie sur Vrai ou Faux.

J'ai vu cette question, How to get the “real” value of the Visible property? qui utilise Reflection pour obtenir l'état local, mais je n'ai pas réussi à le faire fonctionner avec WebControls. C'est aussi une méthode plutôt sale pour obtenir la valeur.

J'ai mis au point la méthode d'extension suivante. Cela fonctionne en supprimant le contrôle de son parent, en vérifiant la propriété, puis en replaçant le contrôle là où il l'a trouvé.

public static bool LocalVisible(this Control control) 
    { 
     //Get a reference to the parent 
     Control parent = control.Parent; 
     //Find where in the parent the control is. 
     int index = parent.Controls.IndexOf(control); 
     //Remove the control from the parent. 
     parent.Controls.Remove(control); 
     //Store the visible state of the control now it has no parent. 
     bool visible = control.Visible; 
     //Add the control back where it was in the parent. 
     parent.Controls.AddAt(index, control); 
     //Return the stored visible value. 
     return visible; 
    } 

Est-ce une façon acceptable de le faire? Cela fonctionne bien et je n'ai rencontré aucun problème de performance. Il semble juste extrêmement sale et je ne doute pas qu'il pourrait y avoir des cas où il pourrait échouer (par exemple, lors du rendu).

Si quelqu'un a des idées sur cette solution ou mieux encore une meilleure façon de trouver la valeur alors ce serait génial.

+0

Quel problème rencontrez-vous lorsque vous utilisez la méthode de réflexion? – slugster

+0

GetMethod pour GetState renvoie null pour un System.Web.UI.Control. –

Répondre

3

Après avoir creusé un peu, je l'ai produit la méthode d'extension suivante qui utilise la réflexion pour récupérer la valeur du drapeau Visible pour les classes héritant de System.Web.UI.Control:

public static bool LocalVisible(this Control control) 
{ 
    var flags = typeof (Control) 
     .GetField("flags", BindingFlags.Instance | BindingFlags.NonPublic) 
     .GetValue(control); 

    return ! (bool) flags.GetType() 
     .GetProperty("Item", BindingFlags.Instance | BindingFlags.NonPublic) 
     .GetValue(flags, new object[] {0x10}); 
} 

Il utilise la réflexion pour trouver le domaine privé flags dans l'objet Control. Ce champ est déclaré avec un type interne, donc plus de réflexion est nécessaire pour appeler le getter de sa propriété indexeur.

La méthode d'extension a été testé sur le balisage suivant:

<asp:Panel Visible="false" runat="server"> 
    <asp:Literal ID="litA" runat="server" /> 
    <asp:Literal ID="litB" Visible="true" runat="server" /> 
    <asp:Literal ID="litC" Visible="false" runat="server" /> 
</asp:Panel> 

<asp:Literal ID="litD" runat="server" /> 
<asp:Literal ID="litE" Visible="true" runat="server" /> 
<asp:Literal ID="litF" Visible="false" runat="server" /> 

résultats des tests:

litA.LocalVisible() == true 
litB.LocalVisible() == true 
litC.LocalVisible() == false 
litD.LocalVisible() == true 
litE.LocalVisible() == true 
litF.LocalVisible() == false 
+0

+1 Merci, c'était le reflet que je recherchais. Je suis toujours sûr qu'il doit y avoir un moyen plus facile de le savoir si! –

+0

+1, bonne réponse. Vous devez aller après le champ privé car l'utilisation de la réflexion sur la propriété Visible appelle toujours l'accesseur get, vous soumettant à la logique qui s'y trouve. Bien qu'il soit très inhabituel pour un contrôle ASP.NET de parcourir l'arborescence de contrôle pour vérifier la visibilité - il n'est pas nécessaire car sa méthode Render n'est pas invoquée si sa propriété Visible est false (ce qui signifie que les contrôles enfants ne reçoivent pas automatiquement rendu soit). – slugster

+0

@slugster: Vous dites qu'il est très inhabituel de le faire, mais les contrôles ASP.NET * font * marcher l'arbre de contrôle lors de l'appel du getter sur leur propriété 'Visible'. Exécutez le cas de test indiqué dans ma réponse par rapport à la propriété 'Visible', et vous obtiendrez: false, false, false, true, true, false. –

0

Vous pouvez exposer la VISU des contrôles en utilisant la propriété. Cela pourrait résoudre votre problème.

Corrigez-moi si je me trompe.

0

Au cas où quelqu'un essaye de faire fonctionner le code de Jørn Schou-Rode dans VB.NET, voici le code qui fonctionne pour moi. Quand je traduis simplement son code dans VB, j'obtiens une exception "Ambiguous match found", car il y a 3 variantes de la propriété "Item".

<Extension()> 
Public Function GetLocalVisible(ctl As Control) As Boolean 
    Dim flags As Object = GetType(Control).GetField("flags", BindingFlags.Instance Or BindingFlags.NonPublic).GetValue(ctl) 
    Dim infos As PropertyInfo() = flags.GetType().GetProperties(BindingFlags.Instance Or BindingFlags.NonPublic) 
    For Each info As PropertyInfo In infos 
     If info.Name = "Item" AndAlso info.PropertyType.Name = "Boolean" Then 
      Return Not CBool(info.GetValue(flags, New Object() {&H10})) 
     End If 
    Next 
    Return ctl.Visible 
End Function