2

我有一个自定义 UserControl,我需要将其 .Visible 属性设置为 True 或 False。但是,如果 UserControl 的第一个子控件是 Panel 并且它的 ID 是 cMain,我希望它设置 Panel 的 .Visible 属性而不是 UserControl 的。这是我的代码:

这是我使用的自定义类:

Public MustInherit Class MyControl : Inherits UserControl

    Public Overrides Property Visible As Boolean
        Get
            Return GetVisible()
        End Get
        Set(value As Boolean)
            SetVisible(value)
        End Set
    End Property

    Function GetVisible() As Boolean

        Dim c As Control = GetMain()

        If TypeOf c Is Panel Then
            Return c.Visible
        Else
            Return MyBase.Visible
        End If

    End Function

    Sub SetVisible(Value As Boolean)

        Dim c As Control = GetMain()

        If TypeOf c Is Panel Then
            c.Visible = Value
        Else
            MyBase.Visible = Value
        End If

    End Sub

    Function GetMain() As Control

        Dim c As Control = If(Controls.Count = 0, Nothing, Controls(0))

        If Not (TypeOf c Is Panel AndAlso c.ID = "cMain") Then c = Me

        Return c

    End Function

End Class

这是实际的 UserControl 本身:

<%@ Control Language="vb" AutoEventWireup="false" CodeBehind="TestControl.ascx.vb" Inherits="JsonJqueryDevex.TestControl1" %>
<asp:Panel ID="cMain" runat="server">
inside
</asp:Panel>
outside

UserControl 的代码隐藏:

Public Class TestControl1
    Inherits MyControl

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load


    End Sub

End Class

这是在主机页面中实现它的标记:

<uc:TestControl ID="ucTest" Visible="true" runat="server"></uc:TestControl>

请注意,我在基类中覆盖了 .Visible 。我这样做是为了如果被引用的控件是 UserControl 本身,我可以调用 MyBase。否则,我认为它是面板控件。当我加载页面时,我得到System.StackOverflowException. false有趣的是,当我在标记中将自定义控件的 Visible 属性设置为时,我没有得到这个。

堆栈跟踪显示它在调用 .Visible 的 get 访问器时被捕获Return GetVisible()。如果是 Panel,它将执行Return c.Visible. 但是,一旦我在 c 是 Panel 时引用 .Visible ,它就会重新进入 MyControl 的 .Visible 获取访问器。我不知道这是怎么可能的,因为我只是覆盖了我的自定义控件的 Visible 属性,但它就像我覆盖了面板的 .Visible 属性一样。这里发生了什么?

4

1 回答 1

3

您的问题在于Control.Visible.

当值是时,您的程序正在运行,false因为它只是false在检查时返回。但是,除非控件可见且父true控件可见,否则控件将不会返回。.Visible

在您的情况下发生的情况是,当 时true,父控件正在检查子控件的.Visible值,并且任何子控件都会检查其父控件(您的用户控件)以及其自身的.Visible值。这是您的无限递归循环发生的地方,导致堆栈溢出。

于 2012-09-19T01:34:39.947 回答