【问题标题】:Enable event visibility for a child control of an usercontrol?为用户控件的子控件启用事件可见性?
【发布时间】:2015-05-03 03:44:04
【问题描述】:

简介

我有一个继承自 UserControl 的类,在这个类中我公开了一个子 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 及其事件,因为 TextBox 属性似乎以这种方式不可见,但请注意我设置该成员的可见性为Public,它是Withevents 成员,如我在上面的介绍中所示。

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

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

End Sub

问题在于,将事件处理程序添加到我的源代码中后,当我返回 Visual StudioVisual GUI Builder 时,它会引发以下错误:

因此,在删除处理用户控件的子 TextBox 的事件处理程序之前,我无法访问 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 类的“顶级”中公开该子文本框的事件,但这将是编写代码的噩梦,因为我不知道该任务是否可以自动化。

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

【问题讨论】:

  • 您是否尝试过使用事件而不是使用事件的朋友来声明您的文本框?
  • 为什么要向属性添加事件处理程序?将它们添加到 TextBox1 控件,一切都会好起来的。 UC 有点像一个带有设计器代码的迷你表单。在画布上放置一个文本框,它就像一个表单一样工作。 ctor 代码也是多余的 - 因为美国是一个容器,所以没有必要创建一个。
  • 因为同样的问题发生在“Textbox1”引用(当设置为Public Withevents,并且可浏览时),这是我在询问之前尝试的第一件事。感谢您的评论。
  • 我猜你想要的是为 TextBox 添加处理程序在表单中?如果是这样,那不是他们的工作方式。通常,一个 UC 用于封装多个控件,这些控件可以作为一个事物以及相关的实现细节。

标签: .net vb.net winforms visual-studio event-handling


【解决方案1】:

我建议您不要按预期使用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
    ...

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

【讨论】:

  • 我使用 UC 的原因是因为我在默认 TextBox 的 OnPaint 事件中放置的任何内容都将被跳过,因为 Windows 绘制它的边框,那么我需要使用 UC 来绘制边框围绕默认文本框...子文本框。无论如何,您对公开事件的建议是我澄清过的事情之一,因为我知道手动公开每个子控件事件是很多事件,需要数千行的疯狂 XML 文档才能做到“完美”遵循良好做法,对我来说不是一个选择,我认为它是一个“补丁”。还是谢谢你
  • 答案的重点是暴露子控件事件(“冒泡”)是错误方向的标志。为了完整,答案有时需要涵盖问题中“已经提到”的内容。否则,不读 Q 的驾车投票者将 DV A,因为它没有提到这个或那个。你应该问 real 关于 TextBox 和边框等的问题。
  • You should ask the real question about the TextBox and border etc 为什么?经过长达数月的研究并看到相同的解决方案,我知道答案是“需要 UC”,然后我来问一个关于UC 和我遇到的不同问题..无论如何我问了你提到的问题,这里 stackoverflow.com/questions/27235587/… 和这里 stackoverflow.com/questions/27230168/… 没有运气。再次感谢您的帮助!
猜你喜欢
  • 2015-04-13
  • 1970-01-01
  • 2016-01-06
  • 2016-01-21
  • 2012-04-23
  • 2011-03-17
  • 2015-12-31
  • 1970-01-01
  • 2011-10-12
相关资源
最近更新 更多