为用户控件的子控件启用事件可见性?

Enable event visibility for a child control of an usercontrol?

简介

我有一个继承自 UserControl 的 Class,在这个 class 中我公开了一个子 TextBox 控件:

Public NotInheritable Class MyUserControl: Inherits UserControl

...

    ''' <summary>
    ''' Gets the inner TextBox of this user control container.
    ''' </summary>
    <Browsable(True),
    EditorBrowsable(EditorBrowsableState.Always),
    DesignerSerializationVisibility(DesignerSerializationVisibility.Content)>
    <Description("The textbox control.")>
    Public ReadOnly Property TextBox As TextBox
        Get
            Return Me.textbox1
        End Get
    End Property

    <Browsable(False),
    EditorBrowsable(EditorBrowsableState.Advanced),
    DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)>
    Private WithEvents textbox1 As New TextBox With {...}

    Public Sub New()
        ...
        Dim container As New ContainerControl
        container.Controls.Add(Me.textbox1)
        Me.Controls.Add(container)
        ...
    End Sub

    ...

End Class

问题

我只是希望能够在设计时使用 Handles 语句让 IntelliSense 以我们可以使用的相同方式列出子 TextBox 事件此功能用于列出和订阅默认文本框的事件,如本例所示:

但是当我用我的用户控件尝试上面的操作时,Handles 语句既不识别子文本框也不识别它的事件,因为 TextBox 属性 似乎不是以这种方式可见,但请注意,我将该成员的可见性设置为 Public,它是一个 Withevents 成员,如我在上面的介绍中所示。

另一方面,我的用户控件的 TextBox 属性 可以手动访问,我可以输入 属性 名称和事件名称,以便下面的事件处理程序将编译并正常工作:

Private Sub MyUserControl_TextBox_TextChanged(sender As Object, e As EventArgs) _
Handles MyUserControl.TextBox.TextChanged

End Sub

问题是,当我 return 到 Visual GUI Builder 时,将事件处理程序添加到我的源代码中=83=] 它抛出这个错误:

所以我无法访问 Visual Builder,直到我删除了处理我的用户控件的子文本框的事件处理程序。

最奇怪的是,正如我所说,我不能使用 Handles 语句列出事件,也不能手动订阅它们,因为它会抛出该错误,但是事件在控件的 属性 可视化构建器的网格,如果我双击事件名称,它会生成事件处理程序(我不能像我解释的那样使用),这太荒谬了:


问题

我做错了什么?如何修复 visual builder 错误?

最重要的是,我如何才能像往常一样为用户控件的子文本框控件使用 Handles 语句?


回答要求

为了轻松解决有关 Handles 语句以及 Visual Builder 的问题,我知道我可以添加对我的子文本框的附加引用以这种方式进行用户控制:

Private WithEvents tb As TextBox = MyUserControlInstance.TextBox

Private Sub tb_TextChanged(sender As Object, e As EventArgs) _
Handles tb.TextChanged

End Sub

否则我可以从我的 UserControl class 的 "top-level" 公开那个子文本框的事件,但这将是代码编写的噩梦,因为我不知道那是否任务可以自动化。

那些棘手的事情不会让我理解和解决真正的问题,我认为我的问题和我的问题很清楚,我会避免"solutions"像那些更"patch"而不是解决方案。

我建议您不要按预期使用 UserControl。这些有点像一个迷你表单,它使用它们上面的控件事件。

根据 Handles MyUserControl.TextBox.TextChanged 看来您希望 表单 参与文本更改

通常,这些允许您创建一个由多个 相关 控件组成的控件,并封装执行某些任务的逻辑。一个示例是 UserControl 来定义新的员工或产品。 UserControl 将消耗所涉及的不同步骤的所有事件,并在最后吐出一个完成的对象。基于任务的示例是具有多个过滤器和参数控件的搜索功能。

它们不是美化的容器控件。使用 UserControl 表单的原因之一是将表单与那些实现细节隔离开来,并将它们封装起来以供重用。

就是说,您只需将要公开的任何事件冒出来即可。使用实际的 UserControl,将你的 TextBox 放到它上面:

Public Class UserControl1

    Public Event MyTBTextChanged(sender As Object, e As EventArgs)

    Public Sub New()
        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.

    End Sub

    Private Sub TextBox1_TextChanged(sender As Object, 
               e As EventArgs) Handles TextBox1.TextChanged
        RaiseEvent MyTBTextChanged(sender, e)
    End Sub
    ...

如果您发现您不得不冒泡不止一个或两个事件(或者可能 any),那么您可能需要重新考虑代码逻辑的处理位置或UserControl 是否是正确的选择(如果公开了很多控件的大量事件,为什么还有 UC?)。