4

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

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

我看过这个问题,如何获得 Visible 属性的“真实”价值?它使用反射来获取本地状态,但是,我无法让它为 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;
    }

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

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

4

3 回答 3

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
于 2010-01-05T10:48:56.180 回答
0

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

如果我错了,请纠正我。

于 2010-01-05T11:08:07.453 回答
0

如果有人试图让 Jørn Schou-Rode 的代码在 VB.NET 中工作,这里是对我有用的代码。当我在 VB 中简单地翻译他的代码时,我得到一个“发现歧义匹配”异常,因为标志“Item”属性有 3 种风格。

<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
于 2014-12-11T17:13:36.583 回答