如何在Asp.Net中获取Visible属性的设置/实际值

时间:2010-01-05 10:18:59

标签: c# .net asp.net web-controls

控件的Get of Visible属性以递归方式查找树以指示是否将呈现控件。

我需要一种方法来查看控件的“本地”可见值是什么,而不管其父控件的设置是什么。即它本身是设置为真还是假。

我已经看到了这个问题How to get the “real” value of the Visible property?,它使用Reflection来获取本地状态,但是,我无法让它适用于WebControls。这也是获取价值的一种相当肮脏的方法。

我提出了以下扩展方法。它的工作原理是从父节点中删除控件,检查属性,然后将控件放回到找到它的位置。

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

这是一种可以接受的方式吗?它工作正常,我没有遇到任何性能问题。它看起来非常脏,我毫不怀疑可能会出现失败的情况(例如,实际渲染时)。

如果有人对这个解决方案有任何想法,或者更好的方法是找到价值,那就更好了。

3 个答案:

答案 0 :(得分:3)

经过深入挖掘后,我创建了以下扩展方法,该方法使用反射来检索继承自Visible的类的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});
}

它使用反射来查找flags对象中的私有字段Control。此字段使用内部类型声明,因此需要更多反射来调用其索引器属性的getter。

扩展方法已在以下标记上进行了测试:

<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" />

测试结果:

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

答案 1 :(得分:0)

您可以使用Property公开控件的可见性。这可以解决您的问题。

如果我错了,请纠正我。

答案 2 :(得分:0)

如果有人试图让JørnSchou-Rode的代码在VB.NET中运行,那么以下代码对我有用。当我在VB中简单地翻译他的代码时,我得到了一个“模糊匹配”异常,因为有3种风格的标志“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